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


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

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



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

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.

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

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

• Процессор: Р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; просмотров: 767; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

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