Rambler's Top100

 

ozlobin.narod.ru


[Назад] [Содержание] [Вперед]

 

Глава 3. Прикладное программирование.

---------------------------------------------------------------------------

 

Эта глава является обзором целочисленных команд, которые программист  может

использовать  при  написании   прикладного  программного  обеспечения   для

процессора i486. Команды  группируются по типам  связанных с ними  функций.

(Дополнительные  прикладные  команды  для  работы  с операндами с плавающей

запятой описаны в Части III).   Команды, не обсуждаемые в этой главе  или в

Части III,  обычно используются  программистами операционных  систем. Такие

команды  системного  уровня  описаны  в  Части  II.  Данное описание команд

приведено для  процессора i486,работающего  в защищенном  режиме. Множество

команд в этом режиме  является 32- разрядным расширением  множества команд,

используемых в  16-разрядных процессорах  семейства Intel.  В режиме прямой

адресации  или  в  виртуальном  режиме  86 процессор i486 имеет архитектуру

самого  быстрого   усовершенствованного  процессора   8086  с   расширенным

множеством  команд.  Смотри  главы  21,22,23,24  и  25  для более подробной

информации  о  выполнении  множества  16-разрядных  команд.  Все   команды,

описанные в  данной главе,  доступны во  всех режимах.   Описание множества

команд в Главе  26 содержит более  подробную информацию обо  всех командах,

включая кодирование, выполняемые действия, воздействие на флаги,  временные

характеристики и исключения, которые могут возникать в процессе  выполнения

команды.

 

 

3.1  Команды пересылки данных.

 

Эти команды обеспечивают  удобные методы пересылки  байтов, слов и  двойных

слов между памятью и регистрами процессора. Они делятся на три типа :

 

- Команды пересылки данных общего назначения.

- Команды работы со стеком.

- Команды преобразования типов.

 

3.1.1  Команды пересылки данных общего назначения.

 

MOV  (Переслать)  пересылает  байт,  слово  или  двойное  слово из операнда

источника  в  операнд  назначения.  Команда  MOV  используется при передаче

данных между следующими элементами :

 

- из регистра в память;

- из памяти в регистр;

- между регистрами общего назначения;

- непосредственные данные в регистр;

- непосредственные данные в память;

 

Команда  MOV  не  может  пересылать  данные  из  памяти  в  память  или  из

сегментного регистра  в сегментный  регистр. Пересылка  из памяти  в память

может быть выполнена при  помощи команды пересылки строк  MOVS. Специальная

форма  команды  MOV  разработана  для  обеспечения  пересылки  данных между

регистрами  AL  или  EAX  и  местом  в  памяти,  закодированным  при помощи

32-разрядного  смещения,  заданного  в   команде.  Эта  форма  команды   не

позволяет  выходить   за  границу   сегмента,  и   запрещает  использование

индексных регистров или  масштабирования. Кодирование данной  формы команды

на  один  байт  короче,  чем  кодирование  команды  MOV  общего назначения.

Аналогичное кодирование выполняется для перемещения 8-,16- или  32-разрядов

непосредственно в один из регистров общего назначения.

 

XCHG  (Перестановка)  переставляет  содержимое  двух операндов. Эта команда

используется вместо трех команд  MOV. Она не требует  временного размещения

в памяти одного из операндов в то время, когда другой загружается.  Команда

XCHG oсобенно полезна при использовании семафоров или аналогичных  структур

данных в  процессе синхронизации.   Команда XCHG  может менять  местами два

байта, два слова или два  двойных слова. Операндами для команды  XCHG могут

служить   два   регистровых   операнда   или   операнд-регистр  и  операнд,

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

расположенный в памяти, она автоматически активизирует сигнал LOCK  (Смотри

Главу 13 для получения более подробной информации о блокировке шин).

 

3.1.2  Команды работы со стеком.

 

PUSH  (Поместить)  декрементирует  указатель  стека  (регистр  ESP),  затем

копирует операнд-источник в вершину  стека (см. Рисунок 3-1).  Команда PUSH

часто  используется  для  размещения  в  стеке  параметров  перед   вызовом

процедуры. Внутри процедуры она может быть использована для  резервирования

пространства  в  стеке  под  временные  переменные. Команда PUSH работает с

операндами,  размещенными  в  памяти,  непосредственными  операндами  и   с

регистровыми  операндами  (включая  регистры  сегмента).  Специльная  форма

команды PUSH возможна при размещении в стеке 32-разрядного регистра  общего

назначения. Эта  форма кодируется  на один  байт короче,  чем команда общей

формы.

                   Рисунок 3-1. Команда PUSH.

 

PUSHA  (Разместить/поместить  все  регистры)  сохраняет  содержимое  восьми

регистров  общего  назначения  в  стеке  (см.  Рисунок  3-2).  Эта  команда

упрощает вызовы  процедур путем  сокращения числа  команд, необходимых  для

сохранения  содержимого  регистров  общего  назначения. Процессор размещает

регистры общего  назначения в  стеке в  следующем порядке  : EAX, ECX, EDX,

EBX, начальное значение  регистра ESP перед  тем, как был  размещен регистр

EAX,  EBP,  ESI  И  EDI.  Результат выполнения команды PUSHA противоположен

действию команды POPA.

 

POP (Восстановить (данные)  из стека) передает  слово или двойное  слово из

текущей  вершины  стека  (на   которую  указывает  регистр  ESP)   операнду

назначения и затем  увеличивает значение регистра  ESP, чтобы тот  указывал

на новую вершину стека. Смотри  Рисунок 3 -3. POP перемещает  информацию из

стека  в  регистр  общего  назначения,  регистр  сегмента или в память. Для

передачи двойного слова из  стека в регистр общего  назначения используется

специальная форма команды POP. Эта форма кодируется кодом, который на  один

байт короче, чем кодирование общей формы команды.

                  Рисунок 3-2. Команда PUSHА.

                   Рисунок 3-3. Команда POP.

 

POPA  (Восстановить  (из  стека)  все  регистры)  восстанавливает  из стека

данные,  сохраненные  в  нем  при  помощи  команды PUSHA, в регистры общего

назначения,   за   исключением   регистра   ESP.   Значение   регистра  ESP

восстанавливается после  выполнения чтения  стека (Восстановления).  Смотри

Рисунок 3-4.

                   Рисунок 3-4. Команда POPA.

 

 

3.1.3  Команды преобразования типов.

 

Команды  преобразования  типа  преобразуют  байты  в слова, слова в двойные

слова и двойные слова в 64-разрядные значения (так называемые  учетверенные

слова). Эти команды  особенно полезны при  преобразовании целых со  знаком,

поскольку  они   автоматически  заполняют   дополнительные  биты   большего

элемента значениями знакового бита меньшего элемента. Это приводит к  целым

того же знака и той же величины, только в более длинном формате. Такой  тип

преобразования,  показанный  на  Рисунке  3-5,  называется распространением

знака.

 

Имеется два вида команд преобразования типа :

- Команды CWD, CBW и CWDE, которые работают только с данными в регистре EAX.

-  Команды  MOVSX  и  MOVZX,  которые  позволяют  одному  из операндов быть

регистром  общего  назначения,  оставляя  другому операнду возможность быть

ячейкой памяти или регистром.  CWD (Преобразовать слово в двойное слово)  и

CDQ  (Преобразовать   двойное  слово   в  учетверенное   слово)   удваивают

размерность операнда-источника. Команда CWD копирует знак (бит 15) слова  в

регистре AX в каждый  бит регистра DX. Команда  CDQ копирует знак (бит  31)

двойного слова в регистре EAX в каждый бит регистра EDX. Команда CWD  может

быть использована для получения делимого в формате двойного слова из  слова

 

перед началом  деления слова,  и команда  CDQ может  быть использована  для

получения делимого в  формате учетверенного слова  из двойного слова  перед

началом деления двойного слова.

              Рисунок 3-5. Распространение знака.

 

 

CBW (Преобразовать байт в слово) копирует знак (бит 7) байта в регистре  AL

в каждый бит регистра AX.

 

CWDE  (Преобразовать  слово  в  двойное  слово с расширением) копирует знак

(бит 15) слова в регистре AX в каждый бит регистра EAX.

 

MOVSX (Переслать с  распространением знака) расширяет  8-разрядное значение

до  16-разрядного  значения  или  8-разрядное  или 16-разрядное значение до

32-разрядного значения,  используя значение  знакового бита  для заполнения

пустых позиций.

 

MOVZX (Переслать  с расширением  нулями) расширяет  8-разрядное значение до

16-разрядного  значения  или  8-разрядное  или  16-разрядное  значение   до

32-разрядного значения, очищая (заполняя нулями) пустые позиции.

 

 

3.2  Команды двоичной арифметики.

 

Арифметические  команды  процессора  i486  работают  с  числовыми  данными,

кодированными  в  двоичном  виде.  Операции  включают  сложение, вычитание,

умножение  и  деление,  а  также  инкрементирование  и   декрементирование,

сравнение и изменение  знака (инвертирование). Поддерживаются  как двоичные

целые со  знаком, так  и двоичные  без знака.  Команды двоичной  арифметики

могут использоваться также в  качестве этапов в арифметических  вычислениях

с  десятичными  целыми.  Операнды-источники  могут  быть  непосредственными

значениями, регистрами  общего назначения  или данными  в памяти.  Операнды

назначения могут быть регистрами общего назначения или ячейками памяти  (за

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

Основные арифметические команды имеют специальный формат для случая,  когда

операндом-источником  является  непосредственное   значение,  а   операндом

назначения является  регистр AL  или EAX.  Эти форматы  имеют длину на один

байт короче, чем арифметические команды общего вида.

Арифметические  команды  обновляют  значения  флагов  ZF,  CF,  SF  и   OF,

отражающих  вид  полученного  результата.  Вид  команды,  используемый  для

проверки  флагов,  зависит  от  того,  как  интерпретируются  данные  - как

имеющие  знак  или  как  не  имеющие  знака.  Флаг  CF содержит информацию,

относящуюся  к  целым  без  знака;  флаги  SF  и  OF  содержат  информацию,

относящуюся к целым со знаком. Флаг ZF содержит информацию, касающуюся  как

целых  со  знаком,  так  и  целых  без  знака:  флаг ZF получает значение 1

(устанавливается), когда все биты результата очищаются (становятся  равными

0).

Арифметические  команды  работают  с  8-,  16-,  или 32-разрядными данными.

Флаги   обновляются   в   зависимости   от   размеров  операций.  Например,

8-разрядная  команда  ADD  устанавливает  флаг  CF  равным  1,  если  сумма

операндов превышает 255 (десятичное).

Если используется целое без знака,  CF флаг может быть проверен  после этих

арифметических операций для того, чтобы определить, когда операция  требует

переноса или  заема единицы  разряда для  того, чтобы  перейти к следующему

этапу операции.  Флаг CF  устанавливается в  1, если  появляется перенос (в

командах  сложения  ADD,  ADC,  AAA  и  DAA)  или  заем единицы (в командах

вычитания SUB, SBB, AAS, DAS, CMP и NEG).

Команды  INC  и  DEC  не   изменяют  состояния  флага  CF.  Это   позволяет

использовать команды для обновления счетчиков, используемых для  управления

циклами  без  изменения  имеющегося  состояния  арифметических результатов.

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

состояние  флага  ZF  (для  обнаружения  окончания  цикла) или использовать

команды ADD и SUB для обновления значения, хранящегося в счетчике.

Флаги SF  и OF  поддерживают целочисленную  арифметику со  знаком. Флаг  SF

имеет  значение  знакового  бита  результата.  Старшим значащим битом (MSB)

значения целого со знаком является  бит, следующий за знаковым битом  - бит

6 байта, бит 14 слова, или  бит 30 двойного слова. Флаг OF  устанавливается

равным 1 в одном из двух случаев :

 

- Был  порожден перенос  из MSB  в знаковый  бит, но  никакого переноса  из

знакового бита не  было выполнено (команды  сложения ADD, ADC,  INC, AAA, и

DAA).   Другими   словами,   результат   был   больше,   чем   максимальное

положительное  число,   которое  может   быть  представленно   в   двоичном

дополнительном коде.

 

- Был порожден  перенос из знакового  бита в MSB,  но никакого переноса  из

знакового бита  не было  выполнено (команды  вычитания SUB,  SBB, DEC, AAS,

DAS,  CMP  и  NEG).  Другими   словами,  результат  оказался  меньше,   чем

наименьшее отрицательное число, которое может быть представлено в  двоичном

дополнительном коде.

 

Эти флаги статуса проверяются  обоими типами условных команд:  Jcc (переход

по условию cc) или SETcc (установка байта по условию).

 

 

3.2.1  Команды сложения и вычитания.

 

ADD   (Сложение    целых)   заменяет    операнд   назначения    на    сумму

операнда-источника и операнда назначения. Команда оказывает воздействие  на

флаги OF, SF, ZF, AF, PF и CF.

 

ADC  (Сложение  целых  с  переносом)  заменяет  операнд назначения на сумму

операнда-источника и операнда назначения  плюс 1, если флаг  CF установлен.

Если флаг CF сброшен, команда ADC  выполняет те же действия, что и  команда

ADD.  Команда  ADC  используется  для  поддержки  переноса,  когда сложение

выполняется на одном из  этапов, например, когда используется  32-разрядная

команда  ADD  для  сложения   двух  учетверенных  слов-операндов.   Команда

оказывает воздействие на флаги OF, SF, ZF, AF, PF, и CF.

 

INC  (Инкременирование)  добавляет  1  к  операнду  назначения. Команда INC

сохраняет значение  флага CF.  Это позволяет  использовать команду  INC для

обновления счетчиков  циклов без  оказания воздействия  на флаги состояния,

изменяющиеся  под  воздействием  арифметических  операций, используемых при

управлении циклом. Флаг ZF может быть использован для обнаружения  ситуации

возникновения  переноса.  Использование  команды  ADD  с   непосредственным

значением 1 в  качестве операнда выполняет  увеличение с обновлением  флага

CF.  Можно  использовать  однобайтную  форму  этой команды, когда операндом

является регистр общего назначения. Команда оказывает воздействие на  флаги

OF, SF, ZF, AF, и PF.

 

SUB (Вычитание  целых) вычитает  операнд-источник из  операнда назначения и

заменяет  значение  операнда  назначения  на  полученный  результат.   Если

возникает  заем  единицы,  устанавливается  значение  флага  CF. Операндами

могут быть  байты, слова  и двойные  слова со  знаком и  без него.  Команда

оказывает воздействие на флаги OF, SF, ZF, AF, PF и CF.

 

SBB  (Вычитание  целых  с  заемом)  вычитает  операнд-источник  из операнда

назначения,  заменяя  значение  приемника  на  результат вычитания минус 1,

если установлен флаг CF. Если флаг  CF очищен, команда SBB выполняет ту  же

операцию, что и команда SUB.  Команда SUB используется для поддержки  заема

разряда, когда выполняется  вычитание чисел как  один из этапов,  например,

когда  используется   32-разрядная  команда   SUB  для   вычитания   одного

учетверенного слова из другого. Команда оказывает воздействие на флаги  OF,

SF, ZF, AF, PF и CF.

 

DEC  (Декременирование)  вычитает  1  из  операнда  назначения. Команда DEC

сохраняет состояние флага  CF. Это позволяет  использовать команду DEC  для

обновления  счетчиков   циклов  без   воздействия  на   состояние   флагов,

изменяемых  под  воздействием  арифметических  операций,  используемых  для

управления циклом. Использование  команды SUB с  непосредственным значением

1  в  качестве  операнда  выполняет  уменьшение, которое обновляет значение

флага  CF.  Допустима  однобайтная  форма  этой  команды,  когда  операндом

является регистр общего назначения. Команда оказывает воздействие на  флаги

OF, SF, ZF, AF, и PF.

 

 

3.2.2  Команды сравнения и изменения знака.

 

CMP (Сравнить) вычитает источник из приемника. Команда обновляет флаги  OF,

SF,  ZF,  AF,  CF,  но  не  изменяет значения операнда-источника и операнда

назначения. Последующие команды Jcc и SETcc могут проверять флаги.

 

NEG (Инвертировать) вычитает  целое со знаком  из нуля. Результатом  работы

команды NEG  является изменение  знака операнда  в двоичном  дополнительном

коде при сохраняении его  значения. Команда оказывает воздействие  на флаги

OF, SF, ZF, AF, PF и CF.


 

3.2.3  Команды умножения.

 

Процессор  i486  разделяет  умножение  операндов  со знаком и операндов без

знака. Команда  MUL работает  с целыми  без знака,  в то  время как команда

IMUL работает как с целыми со знаком, так и с целыми без знака.

 

MUL   (Умножение   целых   без   знака)   выполняет   умножение  без  знака

операнда-источника  и  регистра  AL,  AX  или EAX. Если источником является

байт,  процессор  умножает  его  на  значение,  хранящееся  в регистре AL и

возвращает результат  удвоенной длины  в регистры  AH и  AL. Если  исходный

операнд является словом, процессор  умножает его на значение,  хранящееся в

регистре AX  и возвращает  результат удвоенной  длины в  регистры DX  и AX.

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

значение,  хранящееся  в  регистре  EAX  и  возвращает  результат  в   виде

учетверенного слова в регистры EDX  и EAX. Команда MUL устанавливает  флаги

CF и  OF, если  старшая половина  результата отлична  от нуля;  в противном

случае флаги очищаются. Состояние флагов SF, ZF, AF и PF не определено.

 

IMUL (Умножение целых  со знаком) выполняет  операцию умножения со  знаком.

Команда IMUL имеет три формы :

 

1. Форма с одним операндом.  Операнд может быть словом, байтом  или двойным

словом,  расположенным  в  памяти  или  в  регистре  общего назначения. Эта

команда использует  регистры EAX  и EDX  как операнды  по умолчанию  тем же

образом, что и команда MUL.

 

2.  Форма  с  двумя  операндами.  Одним  из  исходных операндов должен быть

регистр общего назначения, другим  операндом может быть как  регистр общего

назначения, так  и ячейка  памяти. Результат  заменяет содержимое  регистра

общего назначения.

 

3. Форма  с тремя  операндами :  два операнда  являются источниками, третий

операнд  является  приемником.   Одним  из  операндов-источников   является

непосредственное значение, указанное в  команде; вторым может быть  регистр

общего  назначения  или  ячейка  памяти.  Результат  сохраняется в регистре

общего  назначения.  Непосредственный  операнд  является  целым со знаком в

двоично-дополнительном  коде.   Если  непосредственный   операнд   является

байтом, процессор автоматически расширяет его со знаком до размера  второго

операнда, прежде чем выполнить умножение.

 

Во многих отношениях вышеприведенные три формы похожи :

 

- Длина результата равняется удвоенной длине операндов.

 

- Флаги CF и OF устанавливаются, когда значащие биты переносятся в  старшую

половину  результата.  Флаги  CF  и  OF  очищаются,  когда  старшая   часть

результата является продолжением знака младшей части результата.  Состояние

флагов SF, ZF, AF и PF не определено.

 

Тем не  менее, форматы  2 и  3 отличаются,  так как  разультат усекается до

длины операндов, прежде чем он он будет сохранен в регистре назначения.  По

причине  такого  усечения   необходимо  проверить  флаг   OF,  чтобы   быть

уверенным, что ни  один из значащих  битов не потерян.  (Чтобы ознакомиться

со способами проверки флага OF, смотри команды JO, INTO и PUSHF).

Форматы 2 и 3 команды IMUL  также могут быть использованы с операндами  без

знака, так  как вне  зависимости от  того, являются  ли операнды  целыми со

знаком или без знака, младшая половина результата остается одной и той  же.

Однако  флаги  CF  и  OF  не  могут  быть  использованы,  для  того   чтобы

определить, отличается ли правая часть результата от 0.

 

 

 

3.2.4  Команды деления

 

Процессор  i486  подразделяет  команды   деления  на  операции  деления   с

операндами  со  знаком  и  с  операндами  без знака. Команда DIV работает с

целыми без  знака, в  то время  как команда  IDIV работает  как с целыми со

знаком, так и с целыми  без знака. В обоих случаях  генерируется исключение

ошибки  деления,  если  делитель  равен  0  или  частное слишком велико для

регистров AL, AX и EAX.

 

DIV (Деление целых без  знака) выполняет беззнаковое деление  регистров AL,

AX и  EAX на  операнд-источник. Делимое  (аккумулятор) по  длине в два раза

больше, чем  делитель (операнд-  источник); частное  и остаток  имеют ту же

длину, что и делитель, как показано в Таблице 3-1.

Нецелочисленные  результаты  усекаются  в  направлении  0.  Остаток  всегда

меньше,  чем  делитель.  Для  деления  байтов  без знака наибольшим частным

может  быть  число  255.  Для  деления  слов  без  знака наибольшее частное

равняется  62535.  Для  деления  двойных  слов  наибольшее  частное   равно

2**32-1. Состояние флагов OF, SF, ZF, AF, PF и CF не определено.

 

               Таблица 3-1. Ореранды команд деления

 

IDIV (Деление  целых со  знаком) выполняет  деление со  знаком сумматора на

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

DIV.

 

Для деления байтов со знаком максимальное положительное  частное  равняется

 +127, минимальное  отрицательное частное  равняется -128. Для деления слов

со знаком максимальное положительное частное равняется +32767,  минимальное

отрицательное частное равняется -32768. Для деления двойных слов со  знаком

максимальное   положительное   частное   равняется   +2**32-1,  минимальное

отрицательное   частное   равняется   -2**31.   Нецелочисленные  результаты

усекаются в направлении 0. Остаток всегда имеет тот же знак, что и  частное

и меньше, чем делитель в выражении.  Состояние флагов OF, SF, ZF, AF,  PF и

CF не определено.

 

 

3.3  Команды десятичной арифметики

 

Десятичные  арифметические  вычисления  выполняются  путем   комбинирования

команд двоичной арифметики  (уже описанных в  предыдущем разделе) и  команд

десятичной арифметики. Команды десятичной арифметики используются одним  из

следуюших способов :

 

-  Преобразуют   результаты  ранее   выполненных  двоичных   арифметических

операций,  чтобы   получить  допустимые   упакованные  или    неупакованные

десятичные результаты.

 

-   Преобразуют   входные   данные   для   подпоследовательности   двоичных

арифметических операций таким  образом, чтобы операции  выдавали допустимые

упакованные или неупакованные  десятичные результаты. Эти  команды работают

только с регистрами AL или AH. Большинство использует флаг AL.

 

 

3.3.1  Команды коррекции упакованного BCD

 

DAA (Десятичная коррекция  после сложения) корректирует  результат сложения

двух допустимых  упакованных десятичных  операндов в  регистре AL.  Команда

DAA должна  следовать за  сложением двух  пар упакованных  десятичных чисел

(одна  цифра  в  каждой  половине  байта)  для  получения  пары   правильно

упакованных   десятичных   цифр   в    качестве   результатов.   Флаг    CF

устанавливается  в  случае  возникновения  переноса.  Изменяется   значение

флагов SF, ZF, AF, PF и CF. Состояние флага OF не определено.

 

DAS  (Десятичная   коррекция  после   вычитания)  корректирует    результат

вычитания двух  значащих упакованных  десятичных операндов  в регистре  AL.

Команда DAS всегда  должна следовать за  вычитанием одной пары  упакованных

десятичных чисел (одна  цифра в каждой  половине байта) из  другой пары для

получения   пары   правильно   упакованных   десятичных   цифр  в  качестве

результата.  Флаг  CF  устанавливается,  если возникает необходимость заема

разрядной  единицы.  Изменяется  значение  флагов  SF,  ZF,  AF,  PF  и CF.

Состояние флага OF не определено.

 

 

3.3.2  Команды коррекции неупакованного BCD

 

AAA (ASCII-коррекция  после сложения)  изменяет содержимое  регистра AL  на

допустимое  неупакованное  десятичное  число  и  очищает  старшие  4  бита.

Команда AAA  должна следовать  за сложением  двух неупакованных  десятичных

операндов в регистре AL.  Устанавливается флаг CF и  увеличивается значение

регистра AH в случае возникновения переноса. Изменяется значение флагов  AF

и CF. Состояние флагов OF, SF, ZF и PF не определено.

 

AAS (ASCII-коррекция  после вычитания)  изменяет содержимое  регистра AL на

значащее неупакованное десятичное число  и очищает старшие 4  бита. Команда

AAS  должна  следовать  за  вычитанием  одного  неупакованного  десятичного

операнда из другого  в регистре AL.  Устанавливается флаг CF  и уменьшается

значение  регистра  AH,  если  необходим  заем разряда. Изменяются значения

флагов AF и CF. Состояние флагов OF, SF, ZF и PF не определено.

 

AAM  (ASCII-коррекция  после  умножения)  корректирует  результат умножения

двух значащих неупакованных десятичных чисел. Команда AAM должна  следовать

за умножением  двух десятичных  чисел, чтобы  получить значащий  десятичный

результат. Старшая  цифра расположена  слева в  регистре AH,  младшая цифра

расположена  в  регистре  AL.  Изменяются  значения  флагов  SF,  ZF  и PF.

Состояние флагов AF, OF и CF не определено.

 

AAD (ASCII-коррекция перед делением) модифицирует делимое в регистрах AH  и

AL, чтобы  подготовиться к  делению двух  значащих неупакованных десятичных

операндов так, чтобы  частное от деления  было бы допустимым  неупакованным

десятичным числом. Регистр AH должен  содержать старшую цифру и регистр  AL

должен содержать младшую цифру.  Эта команда округляет значение  и помещает

результат  в  регистр  AL.   Регистр  AH  очищается.  Изменяются   значения

регистров SF, ZF и PF. Состояное регистров AF, OF и CF не определено.

 

 

3.4  Логические команды.

 

Логические  команды  имеют  два   операнда.  Операнд-источник  может   быть

непосредственным  значением,  регистром   общего  назначения  или   ячейкой

памяти. Операнды  назначения могут  быть регистрами  общего назначения  или

ячейками памяти (за исключением  ситуации, когда источник является  ячейкой

памяти). Логические команды изменяют состояние флагов. Возможно  применение

кратких  форм  команд,  если  непосредственное  значение операнда-источника

применяется  к  операнду  назначения  в   регистрах  AL  или  EAX.   Группы

логических операций включают в себя :

 

- Команды булевых операций.

- Команды проверки и модификации битов.

- Команды сканирования битов.

- Команды сдвига и циклического сдвига.

- Установка значения байта по условию.

 

 

3.4.1  Команды булевых операций.

 

Логические операции выполняются командами AND, OR, XOR и NOT.

 

NOT (Отрицание) инвертирует  биты в указанном  операнде в форме  дополнения

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

один операнд в регистре или в ячейке памяти. NOT не влияет на флаги.

 

Команды  AND,  OR  и  XOR  выполняют стандартные логические операции "and",

"or"  и  "исключающее  or".   Эти  команды  могут  использовать   следующие

комбинации операндов :

 

- Два регистровых операнда.

- Операнд - регистр общего назначения и операнд - ячейка памяти.

- Операнд  - непосредственное  значение и  либо регистр  общего назначения,

либо операнд - ячейка памяти.

 

Команды  AND,  OR  и  XOR  очищают   флаги  OF  и  CF,  оставляя  флаг   AF

неопределенным и обновляя флаги SF, ZF И PF.

 

 

3.4.2  Команды проверки и модификации битов.

 

Эта  группа  команд  работает  с  одним  битом,  который может находиться в

памяти или  в регистре  общего назначения.  Положение бита  задается в виде

смещения  относительно  младшего  бита  операнда.  Значение  смещения может

задаваться в  виде непосредственного  значения или  содержаться в  регистре

общего назначения.

Описываемые команды вначале присваивают значение выбранного бита флагу  CF.

Затем выбранному  биту присваивается  новое значение,  которое определяется

каждой  конкретной  операцией.  Состояние  флагов  OF,  SF,  ZF, AF и PF не

определено.  Значения,  помещаемые  в   выбранный  бит  данными   командами

приведены в Таблице 3-2.

 

 

3.4.3  Команды сканирования битов

 

Эти  команды  сканируют  слово  или  двойное слово в поисках установленного

бита и заносят  в регистр номер  первого установленного бита  (целое число,

определяющее позицию найденного бита). Сканируемая строка может  находиться

как в регистре, так и в памяти.  Если все слово равно нулю, т.е. в  нем нет

единичных битов, устанавливается флаг  ZF. Если единичный бит  найден, флаг

ZF  очищается.  Если   единичных  битов  не   найдено,  значение   регистра

назначения  не  определено.  Состояние  флагов  OF,  SF,  ZF,  PF  и  CF не

определено.

BSF (Сканирование битов вперед)  просматривает биты от младшего  к старшему

(от бита 0 до старшего бита).

BSR (Сканирование битов в обратном порядке) просматривает биты от  старшего

к младшему (от самого старшего бита к биту 0).

 

      Таблица 3-2. Команды проверки и модификации битов.

 

 

 

 

3.4.4  Команды смещения (сдвига) и циклического сдвига

 

Команды сдвига  и циклического  сдвига переставляют  биты внутри  операнда.

Эти команды подразделяются на три класса :

 

- Команды сдвига.

- Команды двойного сдвига.

- Команды циклического сдвига.

 

 

3.4.4.1  Команды сдвига

 

Команды сдвига выполняют арифметический  или логический сдвиг над  байтами,

словами  или  двойными  словами.   Арифметический  сдвиг  вправо   копирует

знаковый  бит  в  пустую  позицию  старшего  бита  операнда, в то время как

логический сдвиг  вправо, сдвинув  операнд вправо,  очищает пустые позиции.

Арифметический сдвиг является самым быстрым способом выполнения  простейших

вычислений. Например,  арифметический сдвиг  вправо на  один бит  выполняет

деление  целого  на  два.  Логический  сдвиг  делит  целое  без  знака  или

положительное целое, но отрицательное целое со знаком теряет свой  знаковый

бит.

 

Команды арифметического и логического сдвига вправо, SAR и SHR,  отличаются

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

смещении  содержимого  операндов.  Обратите  внимание,  что  нет различий в

командах логического и арифметического сдвига влево. Два символьных  имени,

SAL и SHL, поддерживаются языком ассемблера для обозначения одной команды.

 

Счетчик указывает число битовых позиций, на которое надо сдвинуть  операнд.

Биты  могут  быть  сдвинуты  максимум  на  31 позицию. Команды сдвига могут

задавать счетчик сдвига  любым из трех  способов. Одна форма  команд сдвига

всегда выполняет сдвиг на один бит. Вторая форма задает счетчик сдвига  как

непосредственное  значение.  Третья  форма  задает  счетчик  как  значение,

содержащееся в регистре CL. Последняя форма позволяет задавать счетчик  как

результат  вычислений.  Используются  только  пять младших битов (разрядов)

регистра CL.

 

Когда количество позиций сдвига  равно нулю, никакие флаги  не подвергаются

изменениям.  В  противном  случае  флаг  CF заполяется значением последнего

бита, вытесненного за границы операнда. В командах сдвига на один бит  флаг

OF  устанавливается  равным  единице,  если  значение  самого старшего бита

(знакового бита) изменяется  в процессе операции.  В противном случае  флаг

OF очищается (присваивается значение ноль). После сдвига более чем на  одну

позицию  значение  флага  OF  не  определено.  При сдвиге на одну или более

позиций изменяются значения флагов  SF, ZF, PF и  CF, и состояние флага  AF

не определено.

 

SAL (Арифметический  сдвиг влево)  сдвигает байт,  слово или  двойное слово

операнда  назначения  влево  на  одну  позицию  или  на  количество  битов,

заданное  в  операнде-счетчике  (непосредственное  значение  или значение в

регистре CL). Пустые биты очищаются. Смотри Рисунок 3-6.

 

SHL  (Логический  сдвиг  влево)  другое  наименование команды SAL. Название

поддерживается в языке ассемблера.

 

SHR  (Логический  сдвиг  вправо)  сдвигает  байт,  слово  или двойное слово

операнда  назначения  вправо  на  одну  позицию  или  на  количество битов,

заданное  в  операнде-счетчике  (непосредственное  значение  или значение в

регистре CL). Пустые биты очищаются. Смотри Рисунок 3-7.

 

SAR (Арифметический сдвиг  вправо) сдвигает байт,  слово или двойное  слово

операнда  назначения  вправо  на  одну  позицию  или  на  количество битов,

заданное  в  операнде-счетчике  (непосредственное  значение  или значение в

регистре  CL).  Знак  операнда  сохраняется  путем  очистки  пустых позиций

битов,  если  операнд  положительный,  или  установки значений пустых битов

(равным единице), если операнд отрицательный. Смотри Рисунок 3-8.

                Рисунок 3-6. Команда SHL/SAL.

                Рисунок 3-7. Команда SHR.

                Рисунок 3-8. Команда SАR.

 

 

Насмотря на то, что эта  команда может быть использована для  деления целых

на целое, являющееся  степенью двойки, результат  деления не будет  тем же,

что  при  выполнении  команды  IDIV.  Частное  при  выполнении команды IDIV

округляется  в  сторону  нуля,  в  то  время  как  "частное" при выполнении

команды  SAR  округляется  в  сторону  отрицательной бесконечности. Разница

проявляется только  для отрицательных  чисел. Например,  когда используется

команда IDIV для деления -9 на 4, результатом будет -2 с остатком -1.  Если

использовать команду  SAR для  сдвига -9  вправо на  два бита,  результатом

будет -3.  "Остатком" такого  вида деления  будет -13;  однако команда  SAR

сохраняет только бит старшего разряда остатка (во флаге CF).

 

 

3.4.4.2 Команды двойного сдвига.

 

Эти  команды  обеспечивают  основные  операции,  необходимые для выполнения

действий над  длинными невыровненными  битовыми строками.  Команды двойного

сдвига выполняются как  над словами, так  и над двойными  словами следующим

образом :

 

-  Берутся  два  операнда  длиной  в  слово и получается результат длиной в

слово (32-разрядный сдвиг).

-  Берутся  два  операнда  длиной  в  двойное  слово и получается результат

длиной в двойное слово (64-разрядный сдвиг).

 

Из двух операндов, операнд-источник должен  быть регистром, в то время  как

операнд  назначения  может  быть  как  регистром,  так  и  ячейкой  памяти.

Количество  битов,  на  которое  выполняется  сдвиг,  может  быть  задано в

регистре  CL  или   непосредственно  значением  байта   в  команде.   Биты,

вытесненные  за  границу  операнда-источника,   заполняют  пустые  биты   в

операнде назначения, который  тоже сдвигается. Сохраняется  значение только

операнда назначения.

 Когда выполняется сдвиг на ноль позиций, ни один из флагов не подвергается

изменениям. В противном случае, флагу CF присваивается значение  последнего

бита, вытесненного  из операнда  назначения, и изменяются  значения  флагов

SF,  ZF  и  PF.  При  сдвиге  на  один  разряд флаг  OF  получает  значение

"единица",  если  знак  операнда  изменяется, в  противном  случае флаг  OF

очищается.  При  сдвигах  более  чем   на один бит  состояние  флага AF  не

определено.

 

SHLD  (Двойной  сдвиг  влево)  сдвигает  биты  операнда  назначения  влево,

заполняя пустые  биты значениями  битов, вытесняемых  из операнда-источника

(см.  Рисунок   3-9).  Результат   запоминается  в   операнде   назначения.

Операнд-источник не изменяется.

 

SHRD  (Двойной  сдвиг  вправо)  сдвигает  биты  операнда назначения вправо,

заполняя пустые  биты значениями  битов, вытесняемых  из операнда-источника

(цм.  Рисунок   3-10).  Результат   запоминается  в   операнде  назначения.

Операнд-источник не изменяется.

                 Рисунок 3-9. Команда SHLD.

                 Рисунок 3-10. Команда SHRD.

 

 

3.4.4.3  Koманды циклического сдвига.

 

Команды циклического  сдвига выполняют  циклическое перемещение  разрядов в

байтах,  словах  и  двойных  словах.  Биты,  вытесненные  с  одного   конца

операнда, заносятся в  него с другого  конца. В отличие  от команд смещения

никакие биты не очищаются в процессе циклического сдвига.

Команды циклического сдвига используют только флаги CF и OF. Флаг CF  может

работать  в  качестве  расширения  операнда  в  двух  командах циклического

сдвига,  позволяющих  биту  стать  обособленным  и  затем  быть проверенным

командами  условного  перехода  (JC  или  JNC).  Флаг  CF  всегда  содержит

значение  последнего  бита,  вытесненного  за  пределы  операнда в процессе

циклического сдвига,  даже если  команда не  использует флаг  CF в качестве

расширения операнда. Состояние флагов SF, ZF, AF и PF не изменяется.

При циклическом сдвиге на один  бит флаг OF устанавливается, если  операция

изменяет  самый  старший  бит  (знаковый  бит)  операнда  назначения.  Если

сохраняется исходное значение знака, флаг OF очищается. После  циклического

сдвига более чем на один бит значение флага OF не определено.

 

ROL (Циклический сдвиг влево)  циклически сдвигает байт, слово  или двойное

слово  операнда  назначения  влево  на  один  бит  или на количество битов,

заданное  в  операнде-счетчике  (непосредственное  значение  или  значение,

содержащееся в регистре CL).  Для каждого разряда бит,  который вытесняется

с левого конца операнда, возвращается в правый конец. Смотри Рисунок 3-11.

ROR (Циклический сдвиг вправо) циклически сдвигает байт, слово или  двойное

слово  операнда  назначения  вправо  на  один  бит или на количество битов,

заданное  в  операнде-счетчике  (непосредственное  значение  или  значение,

содержащееся в регистре CL).  Для каждого разряда бит,  который вытесняется

с правого конца операнда, возвращается в левый конец. Смотри Рисунок 3-12.

 

RCL  (Циклический  сдвиг  влево  через  перенос)  циклически сдвигает байт,

слово  или  двойное  слово  операнда  назначения  влево  на один бит или на

количество битов, заданное  в операнде-счетчике (непосредственное  значение

или значение, содержащееся в регистре CL).

Эта  команда  отличается  от  ROL  тем,  что она интерпретирует флаг CF как

однобитовое  расширение  операнда  назначения  со стороны старших разрядов.

Для  каждого  разряда  бит,  который  вытесняется  с левого конца операнда,

перемещается  во  флаг  CF.  В  тоже  время  бит, содержащийся во флаге CF,

вводится с правой стороны. Смотри Рисунок 3-13.

 

RCR  (Циклический  сдвиг  вправо  через  перенос) циклически сдвигает байт,

слово  или  двойное  слово  операнда  назначения  вправо на один бит или на

количество битов, заданное  в операнде-счетчике (непосредственное  значение

или значение, содержащееся в регистре CL).

 

Эта  команда  отличается  от  ROR  тем,  что она интерпретирует флаг CF как

однобитовое  расширение  операнда  назначения  со стороны младших разрядов.

Для  каждого  разряда  бит,  который  вытесняется с правого конца операнда,

перемещается  во  флаг  CF.  В  тоже  время  бит, содержащийся во флаге CF,

вводится с левой стороны. Смотри Рисунок 3-14.

 

3.4.4.4  Быстрый "bit blt" с использованием команд двойного сдвига

 

Одним из назначений команд двойного сдвига является реализация  перемещения

строки  битов,   с  произвольным   рассогласованием  битовых   строк.   Это

называется "bit blt" (BIT BLock Transfer - пересылка блока битов).  Простым

примером  является  перемещение  строки  битов  с  произвольного смещения в

памяти в выровненную по двойным словам строку байт. Слева направо в  строке

пересылается  32  бита  за  один  раз,  если в цикле пересылки используется

двойное смещение.

 

   MOV   ESI,ScrAddr

   MOV   EDI,DestAddr

   MOV   EBX,WordCnt

   MOV   CL,RelOffset       ; относительное смещение Dest-Src

   MOV   EDI,[ESI]             ; загрузить первое слово источника

   ADD   ESI,4                     ; увеличить адрес источника

BltLoop:

   LODS                                   ; новая часть в убывающем порядке в EAX

   SHLD  EDX,EAX,CL         ; переписать содержимое EDX на выровненную вставку

   XCHG  EDX,EAX              ; поменять местами старшее и младшее слово

   STOC                                  ; записать очередную выровненную часть данных

   DEC   EBX                ; уменьшить счетчик цикла

   JNZ   BltLoop

 

Это простой  цикл, позволяющий  данным быть  перемещенными по  32-разрядным

частям с  наивысшей возможной  скоростью. Без  двойного смещения  наилучшим

результатом, который  может быть  получен, является  16-разрядная пересылка

за цикл с использованием 32-разрядного смещения, и заменой команды XCHG  на

команду  ROR  по  16  бит  для  замены  местами старшего и младшего слова в

регистрах.  Более  общий  цикл,  чем  приведен  выше,  потребует некоторого

маскирования первого перемещаемого двойного слова (перед основным  циклом),

последнего перемещаемого двойного слова  (после основного цикла), но  будет

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

 

 

3.4.4.5  Быстрая вставка и исключение битовых строк.

 

Команды двойного смещения также делают возможным :

 

- Быструю вставку битовой строки из регистра в произвольное  местоположение

бита  в  большей  битовой  строке  в  памяти,  без нарушения битов по обеим

сторонам от вставляемых битов.

-   Быстрое   исключение   битовой   строки   в   регистр  с  произвольного

местоположения в большей  битовой строке в  памяти, без нарушения  битов по

обеим сторонам от исключаемых битов.

 

Следующие  примеры  программ  иллюстрируют  вставку  и исключение битов при

различных условиях :

 

1. Вставка битовой строки в память (когда битовая строка длиной от 1 до  25

бит, т.е. вставить 4 байта или меньше) :

 

; Вставить выровненную по правому краю битовую строку из регистра

; в битовую строку в памяти.

;

; Допущения :

; 1. Основание массива строки выровнено по двойным словам.

; 2. Длина битовой строки задана непосредственно значением и

;    битовое смещение содержится в регистре.

;

; Регистр ESI содержит выровненную по правому краю битовую

; строку, которую надо вставить.

; Регистр EDI содержит битовое смещение начальной позиции

; подстроки.

; Также используются регистры EAX и ECX.

;

MOV   ECX,EDI                          ; сохранить исходное смещение

SHR   EDI,3                                 ; разделить смещение на 8 (адрес байта)

AND   CL,7H                              ; получить три младших бита смещения

MOV   EAX,[EDI]strg_base      ; переместить строку длиной в двойное слово в EAX

RDR   EAX,CL                           ; правое выравнивание поля старых битов

SHRD  EAX,ESI,длина            ; получили новые биты

ROL   EAX,длина                    ; правое выравнивание поля новых битов

ROL   EAX,CL                                   ; доставить в конечную позицию

MOV   [EDI]strg_base,EAX              ; заменить двойное слово в памяти

 

2. Вставка битовой строки в память (когда битовая строка длиной от 1 до  31

битa, т.е. вставить 5 байт или меньше) :

 

; Вставить выровненную по правому краю битовую строку из регистра

; в битовую строку в памяти.

;

; Допущения :

; 1. База массива строки выровнена по двойным словам.

; 2. Длина битовой строки задана непосредственно значением и

;    битовое смещение содержится в регистре.

;

; Регистр ESI содержит выровненную по правому краю битовую

; строку, которую надо вставить.

; Регистр EDI содержит битовое смещение начальной позиции

; подстроки.

; Также используются регистры EAX, EBX, ECX и EDI.

;

MOV   ECX,EDI                                     ; временно сохранить смещение

SHR   EDI,5                                                 ; разделить смещение на 32 (двойное

                                                                        ; слово)

SHL   EDI,2                                             ; умножить на 4 (адрес байта)

AND   CL,1FH                                        ; получить пять младших битов смещения

MOV   EAX,[EDI]strg_base                ; переместить младшую строку длиной в

                                                              ; двойное слово в EAX

MOV   EDX,[EDI]strg_base+4           ; переместить оставшуюся строку

                                                              ; длиной в двойное слово в EDX

MOV   EBX,EAX                                   ; временное сохранение части строки

SHRD  EAX,EDX,CL                           ; смещение на заданное число бит

                                                                   ; внутри двойного слова

SHRD  EAX,EBX,CL                            ; смещение на заданное число бит

                                                                ; внутри двойного слова

SHRD  EAX,ESI,длина                         ; получили новые биты

ROL   EAX,длина                                ; правое выравнивание поля новых битов

MOV   EBX,EAX                                  ; временное сохранение строки

SHLD  EAX,EDX,CL                            ; смещение на заданное число бит

                                                                ; внутри слова

SHLD  EDX,EDX,CL                           ; смещение на заданное число бит

                                                                 ; внутри слова

MOV   [EDI]strg_base,EAX                ; заменить двойное слово в памяти

MOV   [EDI]strg_base+4,EDX           ; заменить двойное слово в памяти

 

3. Вставка битовой  строки в память  (когда битовая строка  длиной 32 битa,

т.е. вставить 4 или 5 байт) :

 

;  Вставить  выровненную  по  правому  краю  битовую  строку  из

;  регистра в битовую строку в памяти.

;

;  Допущения :

; 1. База массива строки выровнена по двойным словам.

; 2. Длина  битовой  строки  32  бита  и  битовое   смещение

;  содержится в регистре.

;

 

; Регистр ESI содержит 32-битовую строку, которую надо вставить.

; Регистр EDI содержит битовое смещение начальной позиции

; подстроки.

; Также используются регистры EAX, EBX, ECX и EDI.

;

MOV   EDX,EDI                                                ; сохранить исходное смещение

SHR   EDI,5                                                         ; разделить смещение на 32 (двойное

                                                                            ; слово)

SHL   EDI,2                                                        ; умножить на 4 (адрес байта)

AND   CL,1FH                                                     ; изолировать пять младших битов

                                                                                     ; смещения

MOV   EAX,[EDI]strg_base                                       ; переместить младшую строку длиной в

                                                                             ; двойное слово в EAX

MOV   EDX,[EDI]strg_base+4                                    ; переместить оставшуюся строку

                                                                                    ; длиной в двойное слово в EDX

MOV   EBX,EAX                                     ; временное сохранение части строки

SHRD  EAX,EDX                                                   ; смещение на заданное число бит

                                                                                      ; внутри двойного слова

SHRD  EDX,EBX                                     ; смещение на заданное число бит

                                                                            ; внутри двойного слова

MOV   EAX,ESI                                                   ; переместить 32-разрядное поле в

                                                                                 ; положение

MOV   EBX,EAX                                     ; временное сохранение части строки

SHLD  EAX,EDX                                                   ; смещение на заданное число бит

                                                                            ; внутри слова

SHLD  EDX,EBX                                                   ; смещение на заданное число бит

                                                                             ; внутри слова

MOV   [EDI]strg_base,EAX                                       ; заменить двойное слово в памяти

MOV   [EDI]strg_base+4,EDX                                   ; заменить двойное слово в памяти

 

4. Изъятие битовой строки  из памяти (когда битовая  строка длиной от 1  до

25 бит, т.е. изъять 4 байта или меньше) :

 

; Изъять выровненную по правому краю битовую строку в регистр

; из битовой строки в память.

;

; Допущения :

; 1. База массива строки выровнена по двойным словам.

; 2. Длина битовой строки задана непосредственно значением и

;    битовое смещение содержится в регистре.

;

; Регистр EAX содержит выровненную по правому краю дополненную

; нулями битовую строку, которую надо изъять.

; Регистр EDI содержит битовое смещение начальной позиции

; подстроки.

; Также используются регистры EDI и ECX.

;

MOV   ECX,EDI                                     ; временное сохранение смещения

SHR   EDI,3                                             ; разделить смещение на 8 (адрес байта)

AND   CL,7H                                            ; получить три младших бита смещения

MOV   EAX,[EDI]strg_base                            ; переместить строку длиной в двойное

                                                                 ; слово в EAX

SHR   EAX,CL                                        ; смещение на заданное количество

                                                               ; битов внутри двойного слова

AND   EAX,маска                                           ; изъять битовое поле в EAX

 

5. Изъятие битовой строки  из памяти (когда битовая  строка длиной от 1  до

32 бит, т.е. изъять 5 байт или меньше) :

 

; Изъять выровненную по правому краю битовую строку в регистр

; из битовой строки в памяти.

;

; Допущения :

; 1. База массива строки выровнена по двойным словам.

; 2. Длина битовой строки задана непосредственно значением и

;    битовое смещение содержится в регистре.

;

; Регистр EAX содержит выровненную по правому краю дополненную

; нулями битовую строку, которую надо изъять.

; Регистр EDI содержит битовое смещение начальной позиции

; подстроки.

; Также используются регистры EAX, EBX и ECX.

;

MOV   ECX,EDI                                                ; временно сохранить смещение

SHR   EDI,5                                                     ; разделить смещение на 32 (двойное

                                                                          ; слово)

SHL   EDI,2                                                       ; умножить на 4 (адрес байта)

AND   CL,1FH                                                      ; получить пять младших битов смещения

MOV   EAX,[EDI]strg_base                            ; переместить младшую строку длиной в

                                                                              ; двойное слово в EAX

MOV   EDX,[EDI]strg_base+4                      ; переместить оставшуюся строку

                                                                           ; длиной в двойное слово в EDX

SHRD  EAX,EDX,CL                                       ; смещение на заданное число бит

                                                                           ; внутри двойного слова

SHRD  EAX,EDX,CL                                          ; смещение на заданное число бит

                                                                          ; внутри двойного слова

AND   EAX,маска                                              ; изъять битовое поле в EAX

 

 

3.4.5  Команды установки байта по условию

 

Эта группа команд  устанавливает значение байта  равным нулю или  единице в

зависимости от  любого из  16 условий,  определяемых флагами  статуса. Байт

может  находиться  как  в  регистре,  так  и в памяти. Эти команды особенно

полезны  для  поддержки  Булевских  выражений  в  языках   программирования

высокого уровня, таких, как Паскаль.

Некоторые языки представляют  логическую единицу как  целое, в котором  все

биты  установлены.  Это  может  быть  сделано  при  помощи  команды SETcc с

взаимно  исключающими  условиями  и  последующим  уменьшением результата на

единицу.

 

SETcc (Установить  значение байта  в зависимости  от условия  cc) загружает

значение 1  в байт,  если условие  cc истинно,  в противном  случае очищает

байт. Смотри Приложение D для определения всех возможных условий.

 

 

3.4.6  Команда проверки

 

TEST (Проверить)  выполняет логическое  "and" для  двух операндов,  очищает

флаги OF и CF, оставляя  флаг AF неопределенным и обновляя  значения флагов

SF,  ZF  и  PF.  Флаги  могут  быть  проверены  командами условной передачи

управления или  командами установки  значения байта  по условию. Операндами

служат байты, слова или двойные слова.

Разница между командами TEST и AND  заключается в том, что команда TEST  не

изменяет значение операнда  назначения. Разница между  командами TEST и  BT

заключается в  том, что  TEST может  проверять значения  множества битов за

одну операцию, в то время как команда BT проверяет один бит.

 

 

3.5  Команды передачи управления

 

Процессор  i486  поддерживает  команды  как  условной,  так  и  безусловной

передачи управления  для контроля  за ходом  выполнения программы.  Команды

условной передачи  управления выполняются  только для  некоторых комбинаций

состояния  флагов.  Команды  безусловной  передачи  управления  выполняются

всегда.

 

 

3.5.1  Команды безусловной передачи управления.

 

Команды  JMP,  CALL,  RET,  INT  и  IRET  передают  выполнение  адресату  в

программном сегменте.  Адресат может  находиться как  в том  же программном

сегменте (близкая передача), так  и в другом программном  сегменте (дальняя

передача). Форматы команд, которые  передают управление в другие  сегменты,

обсуждаются  в  следующем  разделе  данной  главы.  Если модель организации

памяти,  используемая  в  некоторой  прикладной  программе,  не   позволяет

программисту   видеть   другие   сегменты,   дальняя   передача  управления

использоваться не должна.

 

3.5.1.1  Команда перехода

 

JMP  (Переход)  безусловно  передает   управление  адресату.  Команда   JMP

является однонаправленной  командой передачи  управления; она  не сохраняет

адрес возврата в стеке.

 

Команда JMP передает  управление из текущей  процедуры в другую  процедуру.

Адрес процедуры  указывается непосредственно  в команде,  в регистре  или в

ячейке памяти. Местоположение адреса определяет, интерпретируется ли  адрес

как относительный адрес или как абсолютный адрес.

 

Относительный   адрес.    Относительный   переход    использует    смещение

(непосредственная константа, используемая  при вычислении адреса)  заданное

в команде.  Смещение имеет  знак и  длину (байт  или двойное  слово). Адрес

назначения  формируется  путем  сложения  смещения  и адреса, хранящегося в

регистре EIP. После этого в  регистре EIP будет содержаться адрес  команды,

которая должна выполняться после команды перехода.

 

Абсолютный адрес. Абсолютный переход используется с 32-разрядным  смещением

одним из следующих способов :

 

1.  Программа  может  выполнять  переход   по  адресу  в  регистре   общего

назначения.  Это  32-разрядное   значение  копируется  в   регистр  EIP   и

выполнение продолжается.

 

2.  Адресат  назначения  может  быть  переменной  в  памяти,  указанной   с

использованием сдандартного режима адресации. Операнд копируется в  регистр

EIP и выполнение продолжается.

 

 

3.5.1.2  Команды вызова процедур

 

CALL  (Вызов  процедуры)  передает  управление  и  сохраняет адрес команды,

следующей  за  командой  CALL,  для  дальнейшего использования командой RET

(Возврат). CALL сохраняет текущее содержимое регистра EIP в стеке.  Команда

RET  в  вызванной  процедуре  использует  этот  адрес  в стеке для передачи

управления назад в вызывающую программу.

 

Команды CALL и JMP имеют абсолютный и относительный форматы.

 

Косвенная  команда  CALL  указывает  абсолютный  адрес  одним  из следующих

способов :

 

1.  Программа  может  выполнить  переход   по  адресу  в  регистре   общего

назначения. 32-разрядное значение копируется в регистр EIP, адрес  возврата

сохраняется в стеке и выполнение продолжается.

 

2.  Адресат  назначения  может  быть  переменной  в  памяти,  указанной   с

использованием стандартного режима адресации. Операнд копируется в  регистр

EIP, адрес возврата сохраняется в стеке и выполнение продолжается.

 

 

3.5.1.3  Команды возврата и возврата-из-прерывания

 

RET  (Возврат  из  процедуры)  завершает  выполнение  процедуры  и передает

управление  команде,  следующей  за  командой  CALL, которая вызвала данную

процедуру.  Команда  RET  восстанавливает  содержимое регистра EIP, которое

было сохранено в стеке при вызове процедуры.

 

Команда RET имеет необязательный операнд непосредственного значения.  Когда

операнд имеется,  эта константа  прибавляется к  содержимому регистра  ESP,

что  имеет  эффект  удаления  всех  параметров,  сохраненных  в стеке перед

вызовом процедуры.

 

IRET (Возврат  из прерывания)  возвращает управление  прерванной процедуре.

Команда  IRET  отличается  от  команды  RET  тем,  что  она восстанавливает

содержимое   регистра   EFLAGS   из   стека.   Содержимое  регистра  EFLAGS

запоминается в стеке при возникновении прерывания.

 

 

3.5.2  Команды условной передачи управления

 

Команды условной передачи управления являются переходами, которые  передают

управление,  если  состояния   регистра  EFLAGS  удоволетворяет   условиям,

заданным в команде.

 

 

3.5.2.1  Команды условного перехода.

 

В Таблице  3-3 приведена  мнемоника команд  перехода. Команды,  приведенные

парами,  являются  альтернативными  именами  одной  и  той же команды. Язык

ассемблера поддерживает эти имена для большей ясности листингов программ.

Разрешена форма  команды условного  перехода, которая  использует смещение,

суммируемое  с  содержимым  регистра  EIP,  если  указанное  условие верно.

Смещение может  быть байтом  или двойным  словом. Смещение  имеет знак; оно

может быть использовано для перехода вперед и назад.

         Таблица 3-3. Команды условного перехода.

 

 

3.5.2.2  Команды управления циклом

 

Команды управления  циклом являются  командами условного  перехода, которые

используют значение, помещенное  в регистр ECX,  в качестве счетчика  числа

выполнений тела  цикла. Все  команды управления  циклом уменьшают  значение

регистра ECX при каждом выполнении цикла и завершают работу при  достижении

значения ноль. Четыре  из пяти команд  управления циклом воспринимают  флаг

ZF  в  качестве  условия  завершения  цикла до момента достижения счетчиком

цикла значения ноль.

 

LOOP (Цикл до тех пор, пока  ECX не равен нулю) является командой  условной

передачи  управления,  которая  уменьшает  содержимое  регистра  ECX  перед

проверкой условия  завершения цикла.  Если содержимое  регистра ECX отлично

от нуля, программа  передает управление по  адресу, указанному в  команде в

качестве адреса назначения (приемника). Команда LOOP приводит к  выполнению

части программы,  которое повторяется  до тех  пор, пока  счетчик не станет

равным  нулю.  Когда  достигается  значение  нуля,  выполнение   передается

команде,  следующей  непосредственно  за   командой  LOOP.  Если   значение

регистра ECX равняется нулю  перед первым выполнением цикла,  счетчик цикла

умеьшается  на  1,  регистру  присваивается  значение  0FFFFFFFFH  и   цикл

выполняется 2**32 раза.

 

LOOPE (Цикл  до тех  пор, пока  равенство) и  LOOPZ (Цикл  до тех пор, пока

ноль) являются  синонимами одной  и той  же команды.  Эти команды  являются

командами  условного  перехода,  которые  уменьшают содержимое регистра ECX

перед проверкой  условия завершения  цикла. Если  значение регистра  ECX не

равно нулю и установлен флаг  ZF, программа передает управление по  адресу,

указанному  в  качестве  операнда  назначения  в  команде. Когда достигнуто

значение нуля или флаг ZF очищен, выполнение передается команде,  следующей

непосредственно за командой LOOPE/ LOOPZ.

 

LOOPNE (Цикл до тех пор, пока неравенство) и LOOPNZ (Цикл до тех пор,  пока

не ноль) являются синонимами одной  и той же команды. Эти  команды являются

командами  условного  перехода,  которые  уменьшают содержимое регистра ECX

перед проверкой  условия завершения  цикла. Если  значение регистра  ECX не

равно  нулю  и  очищен  флаг  ZF,  программа передает управление по адресу,

указанному  в  качестве  операнда  назначения  в  команде. Когда достигнуто

значение  нуля  или  флаг  ZF  установлен,  выполнение  передается команде,

следующей непосредственно за командой LOOPNE /LOOPNZ.

 

 

3.5.2.3.  Выполнение цикла или повтор ноль раз

 

JECXZ (Переход,  если ECX  равен нулю)  переходит по  адресу, указанному  в

команде  в  качестве  операнда  назначения,  если в регистре ECX содержится

значение ноль.  Команда JECXZ  используется совместно  с командой  LOOP и с

командами сканирования строки  и сравнения. Так  как эти команды  уменьшают

значение  регистра  ECX  перед  проверкой  на  ноль, цикл будет выполняться

2**32  раза,  если  обращение  к  циклу  произошло,  когда  в  регистре ECX

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

которые пропускаются  без выполнения,  если начальное  значение равно нулю.

Команда  JECXZ  в  начале  цикла  может  быть  использована для перехода за

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

используется  вместе  с  повторяющимся  командами  сканирования  строки   и

сравнения, JECXZ  может определить  условие окончания  цикла до  достижения

счетчиком  значения  нуля  или  до  выполнения  условий  сканирования   или

сравнения.

 

 

3.5.3  Программные прерывания.

 

Команды  INT,  INTO  и  BOUND  позволяют программисту осуществлять передачу

управления программе обработки прерываний или исключениям.

 

INTn  (Программное  прерывание)  вызывает  программу  обработки,  указанную

вектором прерываний, заданным в  команде. Команда INT может  задавать любые

типы прерываний.  Эта команда  используется для  поддержки множества  типов

программных  прерываний   или  для   проверки  работы   сервисных  программ

обработки прерываний. Сервисные программы обработки прерываний  завершаются

командой  IRET,  которая  передает  управление  к  команде,  следующей   за

командой INT.

 

INTO (Прерывание по  переполнению) вызывает программу  обработки исключений

по  переполнению,  если  установлен  флаг  OF.  Если  данный  флаг  очищен,

выполнение   продолжается   без   вызова   программы   обработки.  Флаг  OF

устанавливается арифметическими и логическими командами и командами  работы

со   строками.   Команда   INTO   поддерживает   использование  программных

прерываний  для  обработки  ошибочных  ситуаций,  таких, как арифметическое

переполнение.

 

BOUND  (Обнаружить  выход  значения   за  допустимые  границы)   сравнивает

значение со знаком,  хранящееся в регистре  общего назначения, с  верхним и

нижним  пределами.  Программа  обработки  исключений  по контролю выхода за

допустимые  границы  вызывается,  если  значение,  содержащееся в регистре,

меньше чем  нижняя граница,  или больше  чем верхняя  граница. Эта  команда

поддерживает использование  программных прерываний  для контроля  выхода за

допустимые границы, таких как  проверка индекса массива, чтобы  убедиться в

том, что он попадает в диапазон границ, заданный для массива.

 

Команда BOUND имеет два  операнда. Первый операнд указывает  регистр общего

назначения, который необходимо проверить. Второй операнд указывает  базовый

адрес  двух  слов  или  двух  двойных  слов,  расположенных  по соседству в

памяти.  Нижней  границей  является  слово  или  двойное  слово  с  младшим

адресом, верхняя граница имеет  старший адрес. Команда BOUND  предполагает,

что верхнее граничное  значение и нижнее  граничное значение расположены  в

смежных  ячейках   памяти.  Верхняя   и  нижняя   граница  не   могут  быть

операндами-регистрами; если же они таковыми являются, возникает  исключение

по неверному коду операции.

 

Верхняя  и  нижняя  границы  массива  могут  располагаться в памяти даже до

самого  массива.  Это  позволяет  задавать  границы  массива как постоянное

смещение  относительно  начала  массива.  Так  как адрес массива уже должен

находиться  в  регистре,  такая  практика позволяет избежать дополнительных

циклов шины для получения эффективной адресации границ массива.

 

[Назад] [Содержание] [Вперед]






Рейтинг@Mail.ru Rambler's Top100