FE23  LOOCH  DISASM

СПРАВОЧНИК  ПО  КОМАНДАМ
ПРОЦЕССОРОВ  x86

(empty)
Главная Загрузка Инструкция Команды x86 Карта сайта

 

ЦЕПОЧЕЧНЫЕ КОМАНДЫ


Семь цепочечных команд

В группе "Цепочечные команды" имеются следующие семь команд:

Таблица 1

 Команда Выполняемая операция  Код Формат
  MOVS  Пересылка данных из цепочки в цепочку   A4
  A5  
 -------w 
  CMPS  Сравнение двух цепочечных операндов   A6
  A7  
 -------w 
  STOS  Сохранение цепочечных данных   AA
  AB  
 -------w 
  LODS  Загрузка цепочечного операнда в аккумулятор   AC
  AD  
 -------w 
  SCAS  Сравнение (сканирование) цепочечных данных   AE
  AF  
 -------w 
  INS  Ввод из порта в цепочку   6C
  6D  
 -------w 
  OUTS  Вывод цепочки в порт   6E
  6F  
 -------w 

Основные особенности цепочечных команд

В русской терминологии стало обычным эти команды называть цепочечными, а не строчными, хотя по-английски они называются "string instructions".

Цепочка - это элементы данных, расположенные в памяти последовательно, без пропусков. Каждый элемент это либо байт (один байт), либо слово (два байта), либо двойное слово (четыре байта). Говоря другими словами, это просто массив, расположенный в оперативной памяти, массив из элементов в 1, или в 2, или в 4 байта. Но для цепочечных команд мы все же используем термин "цепочка" а не массив.

Основное достоинство цепочечной команды состоит в том, что ее можно превратить в цикл, чтобы обработать сразу всю цепочку элементов. Цикл, который запрограммирован внутри процессора. Так, например, выполняя всего одну команду SCAS, процессор может просмотреть всю длинную цепочку целиком в поисках нужного элемента данных. С помощью одной коротенькой машинной команды просканировать мегабайты данных в памяти компьютера.

Сама цепочечная команда состоит всего из одного байта. Причем для каждой цепочечной команды есть два разных кода операции, эти коды отличаются одним битом ( w ). Этот бит определяет размер элементов цепочки (размер операнда). Если ( w = 0 ), то операция выполняется для одного байта (размер операнда 8 бит). Если ( w = 1 ), то размер операнда будет два байта (16 бит) или четыре байта (32 бита), в зависимости от атрибута размера операнда, установленного для этой конкретной команды.

Для случая машинного кода с битом ( w = 1 ) имеется возможность выбора размера операнда с помощью префикса изменения размера операнда (код 66). Например, если для выполнения всей программы установлен режим "32 бита", то по умолчанию цепочечная команда будет работать с элементами в четыре байта. Но если перед этой командой поставить префикс изменения размера операнда, то атрибут размера операнда для данной команды будет "16 бит" и эта же цепочечная команда будет обрабатывать элементы размером два байта.

Цепочечная команда не содержит операндов в своем однобайтном машинном представлении. Операнды команды заранее определены по умолчанию. Для разных цепочечных команд это будут разные операнды.

Таблица 2

 Префикс
повторения
 Команда  Операнды Комментарий
 REP   MOVS  ES:EDI, DS:ESI из памяти - в память
 REPE/REPNE   CMPS  DS:ESI, ES:EDI память - память
 REP   STOS  ES:EDI, EAX из аккумулятора - в память
 ( REP )   LODS  EAX, DS:ESI из памяти - в аккумулятор
 REPE/REPNE   SCAS  ES:EDI, EAX память - аккумулятор
 REP   INS  ES:EDI, DX из порта - в память
 REP   OUTS  DX, DS:ESI из памяти - в порт

Общие свойства всех цепочечных команд

Все цепочечные команды имеют два операнда. В каждой команде хотя бы один из операндов задает адрес в оперативной памяти. В командах MOVS и CMPS оба операнда задают адреса в памяти.

Адрес в оперативной памяти задается с помощью общих регистров ESI (source index) и EDI (destination index). Причем задание адреса памяти выполняется с помощью пары регистров (сегмент:индекс). По умолчанию берутся вполне определенные сочетания сегментного и индексного регистров - DS:ESI для операнда-источника и ES:EDI для операнда-приемника.

В заданной по умолчанию паре операнда-источника DS:ESI можно заменить сегмент DS на другой сегмент с помощью соответствующего префикса сегмента. Для операнда-приемника ES:EDI замена сегмена ES невозможна.

При записи команд на языке ассемблера обычно бывает возможным подставить в команде операнд с желаемым сегментом, например, вот так GS:ESI. Тогда ассемблер сам подставит нужный префикс перед командой. Хотя ассемблеры бывают разные и возможности у них тоже разные.

В качестве индексных регистров используются регистры ESI и EDI, если атрибут размера адреса для команды равен 32 битам. Если же этот атрибут размера адреса равен 16 битам, то индексными регистрами будут SI и DI. Изменить атрибут размера адреса для одной команды можно с помощью префикса изменения размера адреса (код 67).

Программист при разработке программы должен позаботиться, чтобы перед выполнением цепочечной команды уже было установлено нужное значение в нужном индексном регистре (в ESI, или в EDI, или в обоих). После выполнения команды значение используемого индексного регистра (или обоих регистров) автоматически продвинется на 1, или на 2, или на 4 - в зависимости от размера операнда. Это значение увеличится, если движение по адресам памяти происходит в прямом направлении и флажок направления (direction flag) равен DF = 0 (то есть, ранее была выполнена команда CLD). Иначе, когда движение по адресам происходит в обратном направлении и флажок направления равен DF = 1 (то есть, ранее была выполнена команда STD), то значение индекса уменьшится после выполнения цепочечной команды.

Если в цепочечной команде один из операндов - это аккумулятор, то в качестве аккумулятора используется либо регистр AL, либо регистр AX, либо регистр EAX, в зависимости то того, какой размер имеет операнд, 1 байт, или 2 байта, или 4 байта.

На языке ассемблера все цепочечные команды имеют дополнительные варианты для имени команды, когда к основному имени добавляется еще одна буква, которая задает размер операнда. Буква "B" означает "byte", цепочка состоит из байтов, размер операнда равен 1 байту. Буква "W" означает "word", цепочка состоит из слов, размер операнда равен 2 байтам. Буква "D" означает "doubleword", цепочка состоит из двойных слов, размер операнда равен 4 байтам. Например, для команды MOVS получаются такие дополнительные имена: MOVSB, MOVSW, MOVSD.

Организация цикла

Чтобы цепочечная команда работала в цикле, нужно поставить перед этой командой префикс повторения.

На языке ассемблера имеется три разных имени для префикса повторения (и еще два имени - синонимы). В машинных кодах имеется два разных кода для префикса повторения.

В разных источниках для префикса REP (repeat) можно встретить как код F2, так и код F3. По-видимому годится любой из этих кодов.

Префиксы REPNE (repeat if not equal) и REPE (repeat if equal) применяются с командами сравнения операндов. Они налагают дополнительные условия на повторение цикла.

Бывает так, что ассемблер позволяет имя префикса повторения поставить в отдельной строке перед строкой с цепочечной командой. Тогда создается впечатление, что префикс повторения - это отдельная команда, как бы команда цикла. Но на самом деле это не так, это всего лишь префикс перед командой.

Таблица 3

 Префикс
повторения
 Код  Условия
повторения
 Цепочечные команды
 REP   F2
  F3  
 ECX != 0  MOVS, STOS, ( LODS, ) INS, OUTS
 REPNE/REPNZ   F2    ECX != 0
 ZF = 0
 CMPS, SCAS
 REPE/REPZ   F3    ECX != 0
 ZF = 1
 CMPS, SCAS

Если перед цепочечной командой поставлен префикс повторения, то при выполнении команды используется счетчик. Счетчиком является либо регистр ECX, если атрибут размера адреса равен 32 битам, либо регистр CX, если атрибут размера адреса равен 16 битам. (Далее, для краткости, счетчиком везде назван регистр ECX).

Значение счетчика ECX должно быть установлено в программе заранее, до прихода на цепочечную команду. Это значение счетчика задает количество повторений цепочечной команды.

Значение счетчика проверяется каждый раз перед очередным выполнением команды. Если ( ECX = 0 ), то команда не выполняется и происходит переход к команде, следующей за цепочечной командой.

Каждый раз после выполнения цепочечной операции, значение в регистре-счетчике уменьшается на единицу.

Для команд CMPS и SCAS каждый раз после выполнения цепочечной операции проверяется флажок нуля ZF (zero flag). Если условие продолжения цикла не выполнено, то происходит переход к команде, следующей за цепочечной командой. Цикл прекращается, несмотря на то, что по счетчику цикла предел еще не достигнут.

Дополнительные пояснения. Команды CMPS и SCAS - это команды сравнения двух операндов. Если операнды равны, то ( ZF = 1 ). По префиксу REPE цикл продолжается до тех пор, пока операнды равны, то есть, пока ( ZF = 1 ). По префиксу REPNE цикл продолжается до тех пор, пока операнды не равны, то есть, пока ( ZF = 0 ).

Подробности по отдельным командам

Команда MOVS копирует элемент одной цепочки, расположенной в оперативной памяти, в другую цепочку, тоже расположенную в оперативной памяти.

Заметим, что среди команд MOV нет другой такой команды, которая могла бы переслать данные из одного места в памяти на другое место в памяти. Засылка в память обычно делается только из какого-нибудь регистра.

Команда CMPS сравнивает два элемента данных между собой. Оба элемента расположены в оперативной памяти. Выполняется операция вычитание, причем результат вычитания никуда не записывается, от результата остаются только флажки.

Вычитание делается так: из операнда-источника вычитается операнд-приемник ( src - dst ). Тут следует обратить внимание, что в команде CMP вычитание делается наоборот ( dst - src ). Это очень важно учитывать, если после команды CMPS ставится команда условной передачи управления, работающая по условиям больше-меньше.

Еще важно заметить, что в команде CMPS обратный порядок операндов, не такой, какой обычно принят в системе команд x86. Здесь первый операнд - это источник, а второй - приемник. Этот "неправильный" порядок операндов сразу бросается в глаза в таблице 2.

Команда STOS сохраняет содержимое аккумулятора, засылая это содержимое в операнивную память по указанному адресу. Иначе говоря, просто пересылает (копирует) из аккумулятора в оперативную память.

Цикл с командой STOS удобно использовать для "очистки" оперативной памяти, когда в большой блок памяти засылается одинаковый код, например, нули.

Команда LODS загружает элемент цепочки из оперативной памяти в аккумулятор.

Как и любая цепочечная команда, эта команда может работать в цикле. Префиксом повторения для нее будет REP. Однако, трудно придумать разумное применение такому циклу. Поэтому команда LODS обычно не используется в цикле.

Команда SCAS берет элемент цепочки из оперативной памяти и сравнивает его с содержимым аккумулятора. Для этого выполняется операция вычитания. Результат вычитания никуда не записывается, от результата остаются только установленные флажки.

В этой команде аккумулятор условно считается операндом-источником, а элемент цепочки, взятый из памяти - операндом-приемником. Порядок выполнения операции вычитания такой: из значения аккумулятора вычитается значение операнда-приемника ( src - dst ).

Цикл с командой SCAS можно использовать для поиска в блоке памяти. Искомое значение (1, или 2, или 4 байта) заносится в аккумулятор (AL, или AX, или EAX), размер блока памяти в счетчик ECX и делается цикл сканирования по блоку памяти.

Команда INS получает данные (1, или 2, или 4 байта) из входного порта и записывает их в цепочку в памяти.

Команда OUTS берет данные (1, или 2, или 4 байта) из цепочки в памяти и заносит их в выходной порт.

Номер порта для команд INS и OUTS задается в регистре DX.

Команды INS и OUTS являются скорее системными командами, а не пользовательскими. Чтобы эти команды могли быть выполнены, должен быть установлен соответствующий уровень привилегий.




Основные страницы справочника

Справочник по командам процессоров x86
 
Все команды по алфавиту (кратко)
Все команды по алфавиту (подробно)
Первый байт кода операций
Второй байт кода операций
 


Главная Загрузка Инструкция Команды x86 Карта сайта


 
Copyright (C) FE23 Looch Disasm, 2011
File          - refe28.htm
File created  - 06 Jun 2011
Last modified - 16 Jun 2011
Hosted by uCoz