ТОП 10:

Адресация по базе со смещением



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

mov ax,[bx+2]

помещает в регистр AX слово, находящееся в сегменте, указанном в DS, со смещением на 2 большим, чем число, находящееся в BX. Так как слово занимает ровно два байта, эта команда поместила в AX слово, непосредственно следующее за тем, которое есть в предыдущем примере. Такая форма адресации используется в тех случаях, когда в регистре находится адрес начала структуры данных, а доступ надо осуществить к какому-нибудь элементу этой структуры. Другое важное применение адресации по базе со сдвигом — доступ из подпрограммы к параметрам, переданным в стеке, используя регистр BP (EBP) в качестве базы и номер параметра в качестве смещения. Другие допустимые формы записи этого способа адресации:

mov ax,[bp]+2

mov ax,2[bp]

До 80386 в качестве базового регистра можно было использовать только BX, BP, SI или DI и сдвиг мог быть только байтом или словом (со знаком). Начиная с 80386 и старше, процессоры Intel позволяют дополнительно использовать EAX, EBX, ECX, EDX, EBP, ESP, ESI и EDI, так же как и для обычной косвенной адресации. С помощью этого метода можно организовывать доступ к одномерным массивам байт: смещение соответствует адресу начала массива, а число в регистре — индексу элемента массива, который надо считать. Очевидно, что если массив состоит не из байт, а из слов, придется умножить базовый регистр на два, а если из двойных слов — на четыре. Для этого предусмотрен следующий специальный метод адресации.

Косвенная адресация с масштабированием

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

mov ax,[esi*2]+2

Множитель, который может быть равен 1, 2, 4 или 8, соответствует размеру элемента массива — байту, слову, двойному слову, учетверенно­му слову соответственно. Из регистров в этом варианте адресации мож­но использовать только ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ЕВР, ESP, но не SI, DI, ВР или SP, которые можно было использовать в предыдущих ва­риантах.

Адресация по базе с индексированием

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

mov ax [bx+si+2]

mov ax,[bx][si]+2

mov ax,[bx+2][si]

mov ax,[bx][si+2]

mov aх,2[bx][si]

В регистр АХ помещается слово из ячейки памяти со смещением, равным сумме чисел, содержащихся в ВХ, SI, и числа 2. Из 16-битных регистров так можно складывать только ВХ + SI, ВХ + DI, ВР + SI и ВР + DI, а из 32-битных — все восемь регистров общего назначения. Так же как и для прямой адресации, вместо непосредствен­ного указания числа можно использовать имя переменной, заданной одной из директив определения данных. Так можно считать, напри­мер, число из двумерного массива: если задана таблица 10´10 байт, 2 — смещение ее начала от начала сегмента данных (на практике будет ис­пользоваться имя этой таблицы), ВХ = 20, а SI = 7, приведенные ко­манды прочитают слово, состоящее из седьмого и восьмого байт тре­тьей строки. Если таблица состоит не из одиночных байт, а из слов или двойных слов, удобнее использовать следующую, наиболее полную форму адресации.

Адресация по базе с индексированием и масштабированием

Это самая полная возможная схема адресации, в которую входят все случаи, рассмотренные ранее, как частные. Полный адрес операнда мож­но записать как выражение, представленное на рисунке 6.

 

       
   


CS: SS: DS: ES: FS: GS: EAX EBX ECX EDX EBP ESP EDI ESI + EAX EBX ECX EDX EBP EDI ESI * + смещение

 

Рис. 6. Полная форма адресации

 

Смещение может быть байтом или двойным словом. Если ESP или ЕВР используются в роли базового регистра, селектор сегмента операн­да берется по умолчанию из регистра SS, во всех остальных случаях из DS.

Основные непривилегированные команды

 

В этой главе описаны все непривилегированные команды процессоров Intel серии х86, исключая команды расширений для работы с числами повышенной точности (NPX и MMX). Для каждой команды указа­на форма записи, название и модель процессоров Intel, начиная с кото­рой она поддерживается: 8086, 80186, 80286, 80386, 80486, Р5 (Pentium), Р6 (Pentium Pro и Pentium II).

Пересылка данных

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

 

Команда: MOV приемник,источник

• Назначение: Пересылка данных

• Процессор: 8086

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

mov dx, bx

эквивалентна выражению

ax:=bx;

языка Паскаль или

ах=bх;

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

В качестве источника для MOV могут использоваться: число (непос­редственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же раз­мера — байт, слово или двойное слово.

Нельзя выполнять пересылку данных с помощью MOV из одной пере­менной в другую, из одного сегментного регистра в другой и нельзя поме­щать в сегментный регистр непосредственный операнд — эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.

Загрузка регистра SS командой MOV автоматически запрещает прерыва­ния до окончания следующей за этим команды MOV, так что можно загру­зить SS и ESP двумя последовательными командами MOV, не опасаясь, что в этот момент произойдет прерывание, обработчик которого получит не­правильный стек. В любом случае для загрузки значения в регистр SS предпочтительнее команда LSS.

Команда: CMOVcc приемник,источник

• Назначение: Условная пересылка данных

• Процессор: Р6

Это набор команд, которые копируют содержимое источника в при­емник, если удовлетворяется то или иное условие (см. табл. 5). Источ­ником может быть регистр общего назначения или переменная, а при­емником — только регистр. Условие, которое должно удовлетворяться, — просто равенство нулю или единице тех или иных флагов из регистра FLAGS, но, если использовать команды CMOVcc сразу после команды СМР (сравнение) с теми же операндами, условия приобретают особый смысл, например:

cmp ax,bx ; сравнить ax и bx

cmovl ax,bx ; если ax < bx, скопировать bx в ах

Слова «выше» и «ниже» в таблице 5 относятся к сравнению чисел без знака, слова «больше» и «меньше» учитывают знак.

 

• Команда:XCHG операнд1,операнд2

• Назначение: Обмен операндов между собой

• Процессор: 8086

Содержимое операнда 2 копируется в операнд 1, а старое содержимое операнда 1 — в операнд 2. XCHG можно выполнять над двумя регистра­ми или над регистром и переменной.

 

xchg еах,ebx ; то же, что три команды на языке С:

; temp = eax; eax = ebx; ebx = temp,

xchg аl,al ; а эта команда не делает ничего

 

• Команда:BSWAP регистр32

• Назначение: Обмен байт внутри регистра

• Процессор: 80486

Обращает порядок байт в 32-битном регистре. Биты 0 – 7 (младший байт младшего слова) меняются местами с битами 24 – 31 (старший байт старшего слова), а биты 8 – 15 (старший байт младшего слова) меняются местами с битами 16 – 23 (младший байт старшего слова).

 

mov eax,12345678h

bswap eax ; теперь в eax находится 78563412h


Таблица 5. Разновидности команды CMOVcc

Код команды Реальное условие Условие для СМР
CMOVA CMOVNBE СР = 0 и ZF = 0 если выше если не ниже или равно
CMOVAE CMOVNB CMOVNC CF = 0 если выше или равно если не ниже если нет переноса
CMOVB CMOVNAE CMOVC CF = 1 если ниже если не выше или равно если перенос
CMOVBE CMOVNA CF = 1 и ZF = 1 если ниже или равно если не выше
CMOVE CMOVZ ZF = 1 если равно если ноль
CMOVG CMOVNLE ZF = 0 и SF = OF если больше если не меньше или равно
CMOVGE CMOVNL SF = OF если больше или равно если не меньше
CMOVL CMOVNGE SF <> OF если меньше если не больше или равно
CMOVLE CMOVNG ZF = 1и SF<> OF если меньше или равно если не больше
CMOVNE CMOVNZ ZF = 0 если не равно если не ноль
CMOVNO OF = 0 если нет переполнения
CMOVO OF = 1 если есть переполнение
CMOVNP CMOVPO PF = 0 если нет четности если нечетное
CMOVP CMOVPE PF = 1 если есть четность если четное
CMOVNS SF = 0 если нет знака
CMOVS SF = 1 если есть знак

 

Чтобы обратить порядок байт в 16-битном регистре, следует исполь­зовать команду XCHG:

xchg al,ah ; обратить порядок байт в АХ

 

• Команда:PUSH источник

• Назначение: Поместить данные в стек

• Процессор: 8086

Помещает содержимое источника в стек. Источником может быть ре­гистр, сегментный регистр, непосредственный операнд или переменная. Фактически эта команда уменьшает ESP на размер источника в байтах (2 или 4), а затем копирует содержимое источника в память по адресу SS:[ESP]. Команда PUSH практически всегда используется в паре с POP (счи­тать данные из стека). Так, например, чтобы скопировать содержимое одного сегментного регистра в другой (что нельзя выполнить одной ко­мандой MOV), можно использовать такую последовательность команд:

push cs

pop ds ; теперь DS указывает на тот же сегмент, что и CS

Другое частое применение команд PUSH/POP — временное хране­ние переменных, например:

push eax ; сохраняет текущее значение EAX

. . . ; здесь располагаются какие-нибудь команды,

; которые используют EAX, например CMPXCHG

pop eax ; восстанавливает старое значение EAX

 

Начиная с 80286, команда PUSH ESP (или SP) помещает в стек зна­чение ESP до того, как эта же команда его уменьшит, в то время как на 8086 SP помещался в стек уже уменьшенным на два.

 

• Команда:POP приемник

• Назначение: Считать данные из стека

• Процессор: 8086

Помещает в приемник слово или двойное слово, находящееся в вер­шине стека, увеличивая ESP на 2 или 4 соответственно. POP выполняет действие, полностью обратное PUSH. Приемником может быть регистр общего назначения, сегментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменная. Если в роли приемника выступает операнд, использующий ESP для косвен­ной адресации, команда POP вычисляет адрес операнда уже после того, как она увеличивает ESP.

 

• Команда:PUSHA, PUSHAD

• Назначение: Поместить в стек все регистры общего назначения

• Процессор: 80186, 80386

PUSHA помещает в стек регистры в следующем порядке: AX, CX, DX, ВХ, SP, ВР, SI и DI. PUSHAD помещает в стек ЕАХ, ЕСХ, EDX, ЕВХ, ESP, EBP, ESI и EDI. (В случае SP и ESP используется значение, кото­рое находилось в этом регистре до начала работы команды.) В паре с ко­мандами POPA/POPAD, считывающими эти же регистры из стека в обратном порядке, это позволяет писать подпрограммы (обычно обра­ботчики прерываний), которые не должны изменять значения регист­ров по окончании своей работы. В начале такой подпрограммы вызыва­ют команду PUSHA, а в конце — РОРА.

На самом деле PUSHA и PUSHAD — одна и та же команда с кодом 60h. Ее поведение определяется тем, выполняется ли она в 16- или в 32-битном режиме. Если программист использует команду PUSHAD в 16-битном сег­менте или PUSHA в 32-битном, ассемблер просто записывает перед ней префикс изменения размерности операнда (66h).

Это же будет распространяться на некоторые другие пары команд: РОРА/POPAD, POPF/POPFD, PUSHF/PUSHFD, JCXZ/JECXZ, CMPSW/CMPSD, INSW/INSD, LODSW/LODSD, MOVSW/MOVSD, OUTSW/OUTSD, SCASW/SCASD и STOSW/ STOSD.

 

• Команда:РОРА, POPAD

• Назначение: Загрузить из стека все регистры общего назначения

• Процессор: 80186, 80386

Эти команды выполняют действия, полностью обратные действиям PUSHA и PUSHAD, за исключением того, что помещенное в стек зна­чение SP или ESP игнорируется. РОРА загружает из стека DI, SI, ВР, увеличивает SP на два, загружает ВХ, DX, CX, AX, а POPAD загружает EDI, ESI, ЕВР, увеличивает ESP на 4 и загружает ЕВХ, EDX, ЕСХ, ЕАХ.

 

• Команда:IN приемник,источник

• Назначение: Считать данные из порта

• Процессор: 8086

Копирует число из порта ввода-вывода, номер которого указан в ис­точнике, в приемник. Приемником может быть только AL, АХ или ЕАХ. Источник — или непосредственный операнд, или DX, причем можно указывать только номера портов не больше 255.

 

• Команда:OUT приемник,источник

• Назначение: Записать данные в порт

• Процессор: 8086

Копирует число из источника (AL, AX или ЕАХ) в порт ввода-выво­да, номер которого указан в приемнике. Приемник может быть либо не­посредственным номером порта, либо регистром DX. На командах IN и OUT строится все общение процессора с устройствами ввода-выво­да — клавиатурой, жесткими дисками, различными контроллерами, и ис­пользуются они, в первую очередь, в драйверах устройств. Например, чтобы включить динамик PC, достаточно выполнить команды:

 

in al,61h

or al,3

out 61h,al

 

• Команда:CWD

• Назначение: Конвертирование слова в двойное слово

• Процессор: 8086

• Команда:CDQ

• Назначение: Конвертирование двойного слова в учетверенное

• Процессор: 80386

Команда CWD превращает слово в AХ в двойное слово, младшая по­ловина которого (биты 0 – 15) остается в АХ, а старшая (биты 16 – 31) располагается в DX. Команда CDQ выполняет аналогичное действие по отношению к двойному слову в ЕАХ, расширяя его до учетверенного слова в EDX:EAX. Эти команды всего лишь устанавливают все биты регистра DX или EDX в значение, равное значению старшего бита реги­стра АХ или ЕАХ, сохраняя таким образом его знак.

 

• Команда:CBW

• Назначение: Конвертирование байта в слово

• Процессор: 8086

• Команда:CWDE

• Назначение: Конвертирование слова в двойное слово

• Процессор: 80386

CBW расширяет байт, находящийся в регистре AL, до слова в АХ, CWDE расширяет слово в АХ до двойного слова в ЕАХ. CWDE и CWD отличаются тем, что CWDE располагает свои результат в ЕАХ, в то время как CWD, команда, выполняющая точно такое же действие, располагает результат в паре регистров DX:AX. Так же как и команды CWD/CDQ, рас­ширение выполняется путем установки каждого бита старшей половины результата равным старшему биту исходного байта или слова, то есть:

 

mov al,0F5h ; AL = 0F5h = 245 = -11

cbw ; теперь АХ = 0FFF5h = 55 525 = -11

Так же как и в случае с командами PUSHA/PUSHAD, пара команд CWD/CDQ — это одна команда с кодом 99h, и пара команд CBW/CWDE — одна ко­манда с кодом 98h. Интерпретация этих команд зависит от того, в каком (16-битном или в 32-битном) сегменте они исполняются, и точно так же, если указать CDQ или CWDE в 16-битном сегменте, ассемблер поставит префикс изменения разрядности операнда.

 

• Команда:MOVSX приемник,источник

• Назначение: Пересылка с расширением знака

• Процессор: 80386

Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет знак аналогично командам CBW/CWDE.

 

• Команда:MOVZX приемник,источник

• Назначение: Пересылка с расширением нулями

• Процессор: 80386

Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет нулями, то есть команда

movzx ах, bl

эквивалентна паре команд

mov al,bl

mov ah,0

 

• Команда:XLAT адрес

XLATB

• Назначение: Трансляция в соответствии с таблицей

• Процессор: 8086

Помещает в AL байт из таблицы в памяти по адресу DS:BX (или DS:EBX) со смещением относительно начала таблицы, равным AL. В качестве аргумента для XLAT в ассемблере можно указать имя табли­цы, но эта информация никак не используется процессором, и в любом случае необходимо заполнять регистр BX (EBX) адресом таблицы. Однако при указании аргумента-имени можно использовать переопределение сегмента ES: (если таблица расположена в дополнительном сегменте данных). При­менение формы записи команды XLATB не допускает переопределения сегмента.

Эта команда часто используется для преобразований значений цифр в ASCII-формат или различных перекодировок (например, из ASCII в EBCDIC или KOI-8). Впрочем, преобразование цифр в ASCII-форму более эффективно выполнить с помощью команды DAS.

 

• Команда:LEA приемник,источник

• Назначение: Вычисление эффективного адреса

• Процессор: 8086

Вычисляет эффективный адрес источника (переменная) и помещает его в приемник (регистр). С помощью LEA можно вычислить адрес пере­менной, которая описана сложным методом адресации, например по базе с индексированием. Если адрес 32‑битный, а регистр-приемник 16-бит­ный, старшая половина вычисленного адреса теряется, если наоборот, приемник 32-битный, а адресация 16-битная, то вычисленное смещение дополняется нулями.

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

lea bx,[ebx+ebx*4] ; ВХ=ЕВХ*5

или сложения:

lea ebx,[eax+12] ; ЕВХ=ЕАХ+12

(эти команды занимают меньше, чем соответствующие MOV и ADD, и не изменяют флаги).

Двоичная арифметика

Все команды из этого раздела, кроме команд деления и умножения, из­меняют флаги OF, SF, ZF, AF, CF, PF в соответствии с назначением каж­дого из этих флагов (см. п. 2.1.4).

 

• Команда:ADD приемник,источник

• Назначение: Сложение

• Процессор: 8086

Команда выполняет арифметическое сложение приемника и источ­ника, помещает сумму в приемник, не изменяя содержимое источника. Приемник может быть регистром или переменной, источник может быть числом, регистром или переменной, но нельзя использовать пере­менную одновременно и для источника, и для приемника. Команда ADD никак не различает числа со знаком и без знака, но, употребляя значе­ния флагов CF (перенос при сложении чисел без знака), OF (перенос при сложении чисел со знаком) и SF (знак результата), можно исполь­зовать ее и для тех, и для других.

 

• Команда:ADC приемник,источник

• Назначение: Сложение с переносом

• Процессор: 8086

Эта команда во всем аналогична ADD, кроме того, что она выполняет арифметическое сложение приемника, источника и флага CF. Пара ко­манд ADD/ADC используется для сложения чисел повышенной точно­сти. Сложим, например, два 64-битных целых числа: пусть одно из них находится в паре регистров EDX:EAX (младшее двойное слово (биты 0 - 31) — в ЕАХ и старшее (биты 32 - 63) — в EDX), а другое — в паре реги­стров ЕВХ:ЕСХ:

add eax,ecx

adc edx,ebx

Если при сложении младших двойных слов произошел перенос из стар­шего разряда (флаг CF =1), то он будет учтен следующей командой ADC.

 

• Команда:XADD приемник,источник

• Назначение: Обменять между собой и сложить

• Процессор: 80486

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

 

• Команда:SUB приемник,источник

• Назначение: Вычитание

• Процессор: 8086

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

 

• Команда:SBB приемник,источник

• Назначение: Вычитание с займом

• Процессор: 8086

Эта команда во всем аналогична SUB, кроме того, что она вычитает из приемника значение источника и дополнительно вычитает значение флага CF. Так, можно использовать эту команду для вычитания 64-бит­ных чисел в EDX:EAX и ЕВХ:ЕСХ аналогично ADD/ADC:

sub еах,есх

sbb edx,ebx

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

 

• Команда:IMUL источник

IMUL приемник,источник

IMUL приемник,источник1,источник2

• Назначение: Умножение чисел со знаком

• Процессор: 8086

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

1. IMUL источник: источник (регистр или переменная) умножается на AL, АХ или ЕАХ (в зависимости от размера операнда), и результат располагается в AX, DX:AX или EDX:EAX соответственно.

2. IMUL приемник,источник: источник (число, регистр или переменная) умно-жается на приемник (регистр), и результат заносится в приемник.

3. IMUL приемник,источник1,источник2: источник 1 (регистр или пе­ременная) умножается на источник 2 (число), и результат заносится в приемник (регистр).

Во всех трех вариантах считается, что результат может занимать в два раза больше места, чем размер источника. В первом случае приемник автоматически оказывается достаточно большим, но во втором и третьем случаях могут произойти переполнение и потеря старших бит результата. Флаги OF и CF будут равны единице, если это произошло, и нулю, если ре­зультат умножения поместился целиком в приемник (во втором и третьем случаях) или в младшую половину приемника (в первом случае).

Значения флагов SF, ZF, AF и PF после команды IMUL не определены.

 

• Команда:MUL источник

• Назначение: Умножение чисел без знака

• Процессор: 8086

Выполняет умножение содержимого источника (регистр или пере­менная) и регистра AL, АХ, ЕАХ (в зависимости от размера источника) и помещает результат в АХ, DX:AX, EDX:EAX соответственно. Если старшая половина результата (АН, DX, EDX) содержит только нули (ре­зультат целиком поместился в младшую половину), флаги CF и OF ус­танавливаются в 0, иначе — в 1. Значение остальных флагов (SF, ZF, AF и PF) не определено.

 

• Команда:IDIV источник

• Назначение: Целочисленное деление со знаком

• Процессор: 8086

Выполняет целочисленное деление со знаком AL, АХ или ЕАХ (в за­висимости от размера источника) на источник (регистр или перемен­ная) и помещает результат в AL, АХ или ЕАХ, а остаток — в АН, DX или EDX соответственно. Результат всегда округляется в сторону нуля, знак остатка всегда совпадает со знаком делимого, абсолютное значение ос­татка всегда меньше абсолютного значения делителя. Значения флагов CF, OF, SF, ZF, AF и PF после этой команды не определены, а переполнение или деление на ноль вызывает исключение #DE (ошибка при делении) в защищенном режиме и прерывание 0 — в реальном.

 

• Команда:DIV источник

• Назначение: Целочисленное деление без знака

• Процессор: 8086

Выполняет целочисленное деление без знака AL, АХ или ЕАХ (в за­висимости от размера источника) на источник (регистр или перемен­ная) и помещает результат в AL, АХ или ЕАХ, а остаток — в АН, DX или EDX соответственно. Результат всегда округляется в сторону нуля, аб­солютное значение остатка всегда меньше абсолютного значения дели­теля. Значения флагов CF, OF, SF, ZF, AF и PF после этой команды не определены, а переполнение или деление на ноль вызывает исключение #DE (ошибка при делении) в защищенном режиме и прерывание 0 — в реальном.

 

• Команда:INC приемник

• Назначение: Инкремент

• Процессор: 8086

Увеличивает приемник (регистр или переменная) на 1. В отличие от команды ADD приемник,1 не влияет на флаг CF. Остальные арифметические флаги (OF, SF, ZF, AF, PF) устанавливаются в соответствии с результатом сложения.

 

• Команда:DEC приемник

• Назначение: Декремент

• Процессор: 8086

Уменьшает приемник (регистр или переменная) на 1. В отличие от команды SUB приемник,1 не влияет на флаг CF. Остальные арифметические флаги (OF, SF, ZF, AF, PF) устанавливаются в соответствии с результатом вычитания.

 

• Команда:NEG приемник

• Назначение: Изменение знака

• Процессор: 8086

Выполняет над числом, содержащимся в приемнике (регистр или пе­ременная), операцию дополнения до двух. Эта операция эквивалентна обращению знака операнда, если рассматривать его как число со знаком. Если приемник равен нулю, флаг CF устанавливается в 0, иначе — в 1. Остальные флаги (OF, SF, ZF, AF, PF) устанавливаются в соответствии с результатом операции.

Красивый пример применения команды NEG — получение абсолютного зна­чения числа, используя всего две команды — изменение знака и переход на первую команду еще раз, если знак отрицательный:

label0: neg еах

js label0

 

• Команда:СМР приемник,источник

• Назначение: Сравнение

• Процессор: 8086

Сравнивает приемник и источник и устанавливает флаги. Сравнение осуществляется путем вычитания источника (число, регистр или пере­менная) из приемника (регистр или переменная: приемник и источник не могут быть переменными одновременно), причем результат вычита­ния никуда не записывается, единственным результатом работы этой команды оказывается изменение флагов CF, OF, SF, ZF, AF и PF. Обыч­но команду СМР используют вместе с командами условного перехода (Jcc), условной пересылки данных (CMOVcc) или условной установки байт (SETcc), которые позволяют использовать результат сравнения, не обращая внимания на детальное значение каждого флага. Так, команды CMOVE, JE и SETE выполнят соответствующие действия, если значе­ния операндов предшествующей команды СМР были равны.

Несмотря на то что условные команды почти всегда применяются сразу после СМР, их, разумеется, можно использовать пос­ле любой команды, модифицирующей флаги, например: проверить равен­ство АХ нулю можно более короткой командой

test ax,ax

а равенство единице — однобайтной командой

dec ax

 

• Команда:CMPXCHG приемник,источник

• Назначение: Сравнить и обменять между собой

• Процессор: 80486

Сравнивает значение, содержащееся в AL, AX, EAX (в зависимости от размера операндов), с приемником (регистром). Если они равны, со­держимое источника копируется в приемник и флаг ZF устанавливает­ся в 1. Если они не равны, содержимое приемника копируется в AL, АХ, EAX и флаг ZF устанавливается в 0. Остальные флаги устанавливаются по результату операции сравнения, как после СМР. Источник всегда регистр, приемник может быть регистром и переменной.

 

• Команда:CMPXCHG8B приемник

• Назначение: Сравнить и обменять восемь байт

• Процессор: Р5

Выполняет сравнение содержимого регистров EDX:EAX как 64-бит­ного числа (младшее двойное слово в EAX, старшее — в EDX) с прием­ником (восьмибайтная переменная в памяти). Если они равны, содержи­мое регистров ЕСХ:ЕВХ как 64-бтное число (младшее двойное слово в ЕВХ, старшее — в ЕСХ) копируется в приемник. Иначе содержимое приемника копируется в EDX:EAX.

Десятичная арифметика

Процессоры Intel поддерживают операции с двумя форматами десятич­ных чисел: неупакованное двоично-десятичное число — байт, принима­ющий значения от 00 до 09, и упакованное двоично-десятичное число — байт, принимающий значения от 00 до 99h. Все обычные арифметичес­кие операции над такими числами приводят к неправильным результатам. Например, если увеличить 19h на 1, то получится число lAh, а не 20h. Для коррекции результатов арифметических действий над двоич­но-десятичными числами используются следующие команды.

 

• Команда:DAA

• Назначение: BCD-коррекция после сложения

• Процессор: 8086

Если эта команда выполняется сразу после ADD (ADC, INC или XADD) и в регистре AL находится сумма двух упакованных двоично-десятичных чисел, то в результате в AL записывается упакованное двоич­но-десятичное число, которое должно было быть результатом сложения. Например, если AL содержит число 19h, последовательность команд

inc al

daa

приведет к тому, что в AL окажется 20h (а не lAh, как было бы после INC).

Команда DAA выполняет следующие действия:

• Если младшие четыре бита AL больше 9 или флаг AF = 1,

• то AL увеличивается на 6, CF устанавливается, если при этом сложении произошел перенос, и AF устанавливается в 1.

• Иначе AF = 0.

• Если теперь старшие четыре бита AL больше 9 или флаг CF = 1,

• то AL увеличивается на 60h и CF устанавливается в 1.

• Иначе CF = 0.

Флаги AF и CF устанавливаются, если в ходе коррекции происходил перенос из первой или второй цифры соответственно, SF, ZF и PF уста­навливаются в соответствии с результатом, флаг OF не определен.

 

• Команда:DAS

• Назначение: BCD-коррекция после вычитания

• Процессор: 8086

Если эта команда выполняется сразу после SUB (SBB или DEC) и в регистре AL находится разность двух упакованных двоично-деся­тичных чисел, то в результате в AL записывается упакованное двоично-десятичное число, которое должно было быть результатом вычитания. Например, если AL содержит число 20h, последовательность команд

dec al

das

приведет к тому, что в AL окажется 19h (а не 1Fh, как было бы после DEC).

Команда DAS выполняет следующие действия:

• Если младшие четыре бита AL больше 9 или флаг AF = 1,

• то AL уменьшается на 6, CF устанавливается, если при этом вычитании произошел заем, и AF устанавливается в 1.

• Иначе AF = 0.

• Если теперь старшие четыре бита AL больше 9 или флаг CF = 1, ' то AL уменьшается на 60h и CF устанавливается в 1.

• Иначе CF = 0.

Известный пример необычного использования этой команды — самый ком­пактный вариант преобразования шестнадцатеричной цифры в ASCII-код соответствующего символа (более длинный и очевидный вариант этого преобразования реализуется с помощью команды XLAT):

cmp al,10

sbb al,96h

das

После SBB числа 0 – 9 превращаются в 96h – 9Fh, а числа 0Ah – 0Fh — в 0A1h – 0A6h. Затем DAS вычитает 66h из первой группы чисел, переводя их в 30h – 39h, и 60h из второй группы чисел, переводя их в 41h – 46h.

Флаги AF и CF устанавливаются, если в ходе коррекции происходил заем из первой или второй цифры соответственно, SF, ZF и PF устанавливаются в соответствии с результатом, флаг OF не определен.

 

• Команда:ААА

• Назначение: ASCII-коррекция после сложения

• Процессор: 8086

Корректирует сумму двух неупакованных двоично-десятичных чи­сел в AL. Если коррекция приводит к десятичному переносу, АН увели­чивается на 1. Эта команда имеет смысл сразу после команды сложения двух таких чисел. Например, если при сложении 05 и 06 в АХ окажется число 000Bh, то команда ААА скорректирует его в 0l0lh (неупакован­ное десятичное 11). Флаги CF и OF устанавливаются в 1, если произо­шел перенос из AL в АН, иначе они равны нулю. Значения флагов OF, SF, ZF и PF не определены.

 

• Команда:AAS

• Назначение: ASCII-коррекция после вычитания

• Процессор: 8086

Корректирует разность двух неупакованных двоично-десятичных чисел в AL сразу после команды SUB или SBB. Если коррекция приво­дит к займу, АН уменьшается на 1. Флаги CF и OF устанавливаются в 1, если произошел заем из AL в АН, и в ноль — в противном случае. Значе­ния флагов OF, SF, ZF и PF не определены.

 

• Команда:ААМ

• Назначение: ASCII-коррекция после умножения

• Процессор: 8086

Корректирует результат умножения неупакованных двоично-деся­тичных чисел, находящийся в АХ после выполнения команды MUL, преобразовывая полученный результат в пару неупакованных двоично-десятичных чисел (в АН и AL). Например:

mov al, 5

mov bl,5 ;умножить 5 на 5

mul bl ;результат в АХ – 0019h

aam ;теперь АХ содержит 0205h

ААМ устанавливает флаги SF, ZF и PF в соответствии с результатом и оставляет OF, AF и CF неопределенными.

Код команды ААМ — D4h 0Ah, где 0Ah — основание системы счисления, по отношению к которой выполняется коррекция. Этот байт можно заменить на любое другое число (кроме нуля), и ААМ преобразует АХ к двум неупако­ванным цифрам любой системы счисления. Такая обобщенная форма ААМ работает на всех процессорах (начиная с 8086), но появляется в докумен­тации Intel только с процессоров Pentium. Фактически действие, которое выполняет ААМ, — целочисленное деление AL на 0Ah (или любое другое чис­ло в общем случае), частное помещается в AL, и остаток — в АН, так что эту команду часто используют для быстрого деления в высокооптимизированных алгоритмах.

 

Команда:AAD

• Назначение: ASCII-коррекция перед делением

• Процессор: 8086

Выполняет коррекцию неупакованного двоично-десятичного числа, находящегося в регистре АХ, так, чтобы последующее деление привело к корректному десятичному результату. Например, разделим десятич­ное 25 на 5:

mov ax,0205h ;25 в неупакованном формате

mov bl,5

aad ;теперь в АХ находится 19h

div bl ;AX = 0005

Флаги SF, ZF и PF устанавливаются в соответствии с результатом, OF, AF и CF не определены.

Так же как и команда ААМ, AAD используется с любой системой счисления: ее код — D5h 0Ah, и второй байт можно заменить на любое другое число. Дей­ствие AAD состоит в том, что содержимое регистра АН умножается на вто­рой байт команды (0Ah по умолчанию) и складывается с AL, после чего АН обнуляется, так что AAD можно использовать для быстрого умножения на любое число.

Логические операции

Команда:AND приемник,источник

• Назначение: Логическое И

• Процессор: 8086

Команда выполняет побитовое «логическое И» над приемником (ре­гистр или переменная) и источником (число, регистр или переменная; источник и приемник не могут быть переменными одновременно) и помещает результат в приемник. Любой бит результата равен 1, толь­ко если соответствующие биты обоих операндов были равны 1, и равен 0 в остальных случаях. Наиболее часто AND применяют для выборочного обнуления отдельных бит, например: команда

and al,00001111b

обнулит старшие четыре бита регистра AL, сохранив неизменными че­тыре младших.

Флаги OF н CF обнуляются, SF, ZF и PF устанавливаются в соответствии с результатом, AF не определен.

 

• Команда:OR приемник,источник

• Назначение: Логическое ИЛИ

• Процессор: 8086

Выполняет побитовое «логическое ИЛИ» над приемником (регистр или переменная) и источником (число, регистр или переменная; источ­ник и приемник не могут быть переменными одновременно) и помеща­ет результат в приемник. Любой бит результата равен 0, только если со­ответствующие биты обоих операндов были равны 0, и равен 1 в остальных случаях. Команду OR чаще всего используют для выбороч­ной установки отдельных бит, например: команда

or al,00001111b

приведет к тому, что младшие четыре бита регистра AL будут установ­лены в 1.

При выполнении команды OR флаги OF и CF обнуляются, SF, ZF и PF устанавливаются в соответствии с результатом, AF не определен.

 

• Команда:XOR приемник,источник

• Назначение: Логическое исключающее ИЛИ

• Процессор: 8086

Выполняет побитовое «логическое исключающее ИЛИ» над прием­ником (регистр или переменная) и источником (число, регистр или пе­ременная; источник и приемник не могут быть переменными одновре­менно) и помещает результат в приемник. Любой бит результата равен 1, если соответствующие биты операндов различны, и нулю, если оди­наковы. XOR используется для самых разных операций, например:

хоr ах,ах ; обнуление регистра АХ

или

хоr ах,bх

хоr bх,ах

хоr ах,bх ; меняет местами содержимое АХ и ВХ

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

mov ax, 0

или

xchg ax, bx

 

• Команда:NOT приемник







Последнее изменение этой страницы: 2016-08-15; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.215.182.81 (0.049 с.)