Ниже приводится алфавитный перечень команд процессоров Intel с кратким описанием действия каждой команды и примерами ее использования.
В разделах статей, начинающихся с обозначения 386+, описываются отличия действия рассматриваемой команды в современных 32-разрядных процессорах (80386, i486, Pentium). Как правило, эти отличия заключаются в возможности использования не только 8- и 16-разрядных, но и 32-разрядных операндов, а также расширенных режимов адресации памяти. Обычные 16-разрядные программы реального режима вполне могут использовать расширенные регистры процессора (ЕАХ, ЕВХ и проч.), 32-битовые ячейки памяти и варианты команд для их обработки. Для того, чтобы ассемблер правильно транслировал команды с 32-разрядными операндами, в программу необходимо включить директиву ассемблера .386 (можно также использовать директивы .486 или .586), а сегменту команд (и во многих случаях сегменту данных) придать описатель use 16:
.386
codes segment use 16
assume CS:codes
codes ends
data segment use16
data ends
Кроме этого, необходимо разрешить компоновщику обрабатывать 32-разрядные операнды, что для компоновщика TLINK осуществляется указанием ключа /3.
Отдельные статьи, начинающиеся с обозначений 386+ , 486+ и Pentium+, посвящены командам, отсутствующим в МП 86. Многие из этих команд (например, команды проверки бита Ы или условной установки байта set) носят прикладной характер и могут использоваться в обычных программах реального режима.
Новые команды, реализованные впервые в МП 80386, сохраняют свое значение и в более современных процессорах. Для того, чтобы ассемблер распознавая команды МП 80386, в программе должна присутствовать директива .386.
Новые команды, реализованные впервые в МП 80486, сохраняют свое значение и в процессорах Pentium. Для того, чтобы ассемблер распознавая команды МП 80486, в программе должна присутствовать директива .486.
Для того, чтобы ассемблер распознавал команды, реализованные впервые в процессоре Pentium, в программе должна присутствовать директива .586.
Ряд команд требует для своего выполнения специальных условий, обычно отсутствующих в приложениях MS-DOS. Так, например, команда bound (проверки индекса массива на выход за границы) при обнаружении выхода за границы генерирует прерывание с вектором 5. Это прерывание в защищенном режиме как раз и является исключением нарушения границ массива, но в приложениях MS-DOS используется для вывода на печать содержимого экрана. Поэтому использование таких команд в реальном режиме затруднено.
Отдельные статьи, начинающиеся с обозначения 386Р+, посвящены привилегированным командам современных процессоров, работающих в расширенном режиме, и отсутствующим в МП 86. Для использования этих команд в программу необходимо включить директиву ассемблера .386Р (можно также использовать директивы .486Р или .586Р). Если при этом программа реализуется, как 16-разрядное приложение MS-DOS, сегмент команд должен иметь описатель usc16 (при наличии директивы .386 транслятор по умолчанию создает 32-разрядное приложение). Следует, однако, иметь в виду, что привилегированные команды защищенного режима предназначены для использования не в прикладных программах, а в операционных системах защищенного режима. В прикладных программах привилегированные команды приходится использовать лишь в весьма специальных случаях, когда, например, прикладная программа запускается в реальном режиме под управлением MS-DOS, но затем переводит процессор в защищенный режим и далее использует преимущества этого режима. Типичный пример программы такого рода — приложение DOS, которому требуется использовать всю оперативную память компьютера. В настоящей книге, посвященной, в основном, реальному режиму, дается лишь перечисление привилегированных команд защищенного режима.
ААА ASCII-коррекция регистра АХ после сложения
Команда ааа используется вслед за операцией сложения add в регистре AL двух неупакованных двоично-десятичных (BCD) чисел, если в АХ находится двухразрядное неупакованное двоично-десятичное число. Команда не имеет параметров. Она преобразует результат сложения в неупакованное двоично-десятичное число, младший десятичный разряд которого находится в AL. Если результат превышает 9, выполняется инкремент содержимого регистра АН. Команда воздействует на флаги AF и CF.
Пример
mov AX,0605h ; Неупакованное BCD 65
add AL,09h ;Неупакованное BCD 9, AX=060Eh
ааа ;AX=0704h, неупакованное BCD 74
AAD ASCII-коррекция регистра АХ перед делением
Команда aad используется перед операцией деления неупакованного двоично-десятичного (BCD) числа в регистре АХ на другое неупакован
ное двоично-десятичное число. Команда не имеет параметров. Она преобразует делимое в регистре АХ в двоичное число без знака, чтобы в результате деления получились правильные неупакованные двоично-десятичные числа (частное в AL, остаток в АН). Команда воздействует на флаги SF, ZF и PF.
Пример
raov AX,0207h ;Неупакованное BCD 27
mov DL,06h ;Неупакованное BCD 6
aad ;AX=001Bh=27
div DL ;AX=0304h, т.е. 4 и З в остатке
AAM ASCII-коррекция регистра АХ после умножения
Команда aam используется вслед за операцией умножения двух неупакованных двоично-десятичных чисел. Команда не имеет параметров. Она преобразует результат умножения, являющийся двоичным числом, в правильное неупакованное двоично-десятичное (BCD) число, младший разряд которого помещается в AL, а старший — в АН. Команда воздействует на флаги SF, ZF и PF.
Пример
mov AL,08h ;Неупакованное BCD 8
mov CL,07h ;Неупакованное BCD 7
mul CL ;AX=0038h=56
aam ;AX=0506h, BCD 56
AAS ASCII-коррекция регистра AL после вычитания
Команда aas используется вслед за операцией вычитания одного неупакованного двоично-десятичного числа (BCD) из другого в AL. Команда не имеет параметров. Она преобразует результат вычитания в неупакованное двоично-десятичное число. Если результат вычитания оказывается меньше 0, выполняется декремент содержимого регистра АН. Команда воздействует на флаги AF и CF; после ее выполнения AF=1, CF=1.
Пример
mov AX,0708h ;Неупакованное BCD 78
mov CL,09h ;Неупакованное BCD 9
sub AL,CL ;AX=07FFh
aas ;AX=0609h, неупакованное BCD 69
ADC Целочисленное сложение с переносом
Команда adc осуществляет сложение первого и второго операндов, прибаатяя к результату значение флага переноса CF. Исходное значение первого операнда (приемника) теряется, замещаясь результатом сложения. Второй операнд не изменяется. В качестве первого операнда команды adc можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команда adc (совместно с командой add) обычно используется для сложения 32-разрядных чисел. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
mov AX,1125h
adc AX,2C25h ;AX=3D4Bh, если CF был = 1
;AX=3D4Ah, если CF был = 0
Пример 2
; В полях данных:
numlow dw 0FFFFh ;Младшая часть 2-го слагаемого
numhigh dw 000Sh ;Старшая часть 2-го слагаемого
;Число 0005FFFFh=393215
;В программном сегменте:
mov AX,000Sh ;Младшая часть 1-го слагаемого
mov BX,0002h ;Старшая часть 1-го слагаемого
;Число 00020005h=131077
add АХ,numlow ;Сложение младших частей. АХ=4, CF=1
adc BX, numhigh ;Сложение старших частей с
;переносом.ВХ:АХ=0008:0004h.
;Число 00080004h=524292
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. Команда adc с 32-разрядными операндами может использоваться для сложения 64-разрядных целых чисел.
Пример
; В полях данных
mem321 dd 0FFFFFFFFh ;Младшая часть 1-го слагаемого
mem32h dd 98765432h ;Старшая часть 1-го слагаемого
; В программном сегменте
mov EAX,1 ;Младшая часть 2-го слагаемого
mov EBX,0 ;Старшая часть 2-го слагаемого
add EAX,mem321 ;Складываем младшие половины
;Сумма=100000000Ь>32 бит
;EAX=000000h, перенос
adc EBX,mem32h ;Складываем старшие половины
;и перенос. EBX=90000001h ;Сумма: 9876543300000000h
ADD Целочисленное сложение
Команда add осуществляет сложение первого и второго операндов. Исходное значение первого операнда (приемника) теряется, замещаясь результатом сложения. Второй операнд не изменяется. В качестве первого операнда команды add можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячей-ку памяти или непосредственное значение, однако не допускается опре-делять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команду add можно использовать для сложения как обычных целых чи-сел, так и двоично-десятичных (с использованием регистра АХ для хра-нения результата). Если складываются неупакованные двоично- десятич-ные (BCD) числа, после команды add следует использовать команду ааа; если складываются упакованные числа, то команду daa. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
mov BX,lFFEh
mov CX,3
add BX,CX ;BX=2001h, CX=0003h
Пример 2
mov AX,25h
add AX,12h ;AX=0037h
Пример 3
; В полях данных:
mem dw 128
;B программном сегменте:
add mem,100 ;mem=228
Пример 4
mov AX,0507h ;BCD распакованное 57 add AL,05h ;BCD 5, AX=050Ch aaa ;AX=0602h, BCD 62
Пример 5
mov AL,57h ;BCD упакованное 57 add AL,05h ;BCD 5, AL=5Ch daa ;AL=62h, BCD 62
386+
Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov EAX,98765432h
add EAX,11111111h ; EAX=A9876543h
AND Логическое И
Команда and осущестшшет логическое (побитовое) умножение первого операнда на второй. Исходное значение первого операнда (приемника) теряется, замещаясь результатом умножения. В качестве первого операнда команды and можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами. Команда воздействует на флаги SF, ZF и PF.
Правила побитового умножения:
Первый операнд-бит 0101
Второй операнд-бит 0011
Бит результата 0001
Пример 1
mov AX,0FFEh
and AX,5555h ;AX=0554h
Пример 2
; В полях данных:
mem dw 0С003h
;В программном сегменте:
mov AX,700Eh
and AX,mem ;AX=4002h
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov EDX, 0FA8 8 0 0 4 lh
and EDX,0FF00000Fh ; EDX = FA000001h
386P+ ARPL Коррекция запрашиваемого уровня привилегий селектора
Команда aprl сравнивает селектор с образцом, содержащим максимально допустимый уровень привилегий (обычно используется селектор CS) и устанавливает проверяемое значение в соответствии с меньшим из двух уровней привилегий. Если изменение уровня не потребовалось, флаг ZF сбрасывается, если потребовалось — устанавливается. В качестве первого операнда команды aprl может использоваться 16-разрядный регистр или слово памяти с проверяемым селектором; в качестве второго операнда — 16-разрядный регистр с селектором-образцом.
386+ BOUND Проверка индекса массива на выход за границы массива
Команда bound проверяет, лежит ли указанный индекс, рассматриваемый, как число со знаком, внутри заданных вторым операндом границ.
Если индекс выходит за границы массива снизу или сверху, генерируется прерывание с вектором 5. Первый операнд должен быть регистром, содержащим проверяемый индекс, второй — адресом поля памяти с двумя границами проверяемого массива. В команде bound допустимо использование как 16-битовых, так и 32-битовых операндов (но и первый, и второй операнды должны быть одного типа).
386+ BSF Прямое сканирование битов
Команда bsf сканирует слово или двойное слово в поисках бита, равного 1. Сканирование выполняется от младшего бита (0) к старшему. Если в слове не найдено устаноштенных битов, то устанавливается флаг ZF. Если установленные биты есть, то номер первого установленного бита заносится в указанный в команде регистр. Номером бита считается его позиция в слове, отсчитываемая от бита 0. В качестве первого операнда команды bsf следует указывать регистр, куда будет помещен результат сканирования, в качестве второго — регистр или ячейку памяти со сканируемым словом. В команде bsf допустимо использование как 16-битовых, так и 32-битовых операндов (но и первый, и второй операнды должны быть одного типа).
Пример 1
mov BX,70h ;Анализируемое данное
bsf АХ,ВХ ;АХ=4, ZF=0
Пример 2
mov SI,0 ;Анализируемое данное
bsf BX,SI ;ZF=1, в ВХ прежнее значение
Пример 3
mov SI,8 ;Анализируемое данное
bsf BX,SI ;BX=3, ZF=1
Пример 4
;В полях данных
mem dw 9000h Анализируемое данное
;В программном сегменте:
bsf AX, mem ;AX=000Ch=12, ZF=0
386+ BSR Обратное сканирование битов
Команда bsf сканирует слою или двойное слово в поисках бита, равного 1. Сканирование выполняется от старшего бита (15 или 31) к младшему. Если в слове не найдено установленных битов, то устанашгивается флаг ZF. Если установленные биты есть, то номер первого устаноштенного бита заносится в указанный в команде регистр. Номером бита считается его позиция в слове, отсчитываемая от бита 0. В качестве первого операнда команды bsf следует указывать регистр, куда будет помещен результат сканирования, в качестве второго — регистр или ячейку памяти со сканируемым словом. В команде bsf допустимо использование как 16-битовых, так и 32-битовых операндов, но и первый, и второй операнды должны быть одного типа (за исключением случая, когда второй операнд — константа).
Пример 1
mov BX,70h ;Анализируемое данное bsr AX,BX ;AX=6, ZF=0
Пример 2
mov SI,0 ;Анализируемое данное
bsr BX,SI ;ZF=1, в ВХ прежнее значение
Пример 3
mov SI,8 ;Анализируемое данное
bsf BX,SI ;BX=3, ZF=1
Пример 4
; В полях данных
mem dw 9000h ; Анализируемое данное
;В программном сегменте:
bsr AX, mem ;AX=000Fh=15, ZF=0
486+ BSWAP Обмен байтов
Команда bswap изменяет порядок байтов в своем единственном операнде, в качестве которого может выступать только 32-разрядный регистр общего назначения. Биты 7…0 обмениваются с битами 31…24, а биты 15… 18 с битами 23…16. Другими словами, нумерация байтов регистра изменяется на противополжную (вместо 3, 2, 1,0 — 0, 1, 2, 3). Команда не воздействует на флаги процессора.
Пример
mov ЕАХ, 01234567h
bswapEAX ;EAX=67452301h
386+ ВТ Проверка бита
Команда bt позволяет определить, установлен ли в заданном слове определенный бит. Анализируемое слово выступает в качестве первого операнда, номер бита — в качестве второго. Первым операндом команды bt может служить регистр или ячейка памяти, вторым — регистр или непосредственное значение. В команде допустимо использование как 16-битовых, так и 32-битовых операндов, но и первый, и второй операнды должны быть одного типа (за исключением случая, когда второй операнд — константа).
Значение проверяемого бита копируется в флаг CF.
Пример 1
mov AX,00FFh ;Анализируемое данное
bt AX,5 ; бит 5=1, ZF=1
Пример 2
mov AX,00FFh ;Анализируемое данное
bt AX,8 ;бит 8=0, ZF=0
Пример 3
mov AX,8001h ;Анализируемое данное
mov BX,15 ;Номер проверяемого бита
bt АХ,ВХ ;бит 15 = 1, ZF=1
Пример 4
;В полях данных
mem dw IFh ;Анализируемое данное
;В программном сегменте:
bt mem, 4 ;бит 4 = 1, ZF=1
386+ ВТС Проверка и инверсия бита
Команда btc проверяет определенный бит в слове, заданном первым операндом, копирует его значение в флаг CF и инвертирует. Номер бита выступает в качестве второго операнда. Первым операндом команды btc может служить регистр или ячейка памяти, вторым — регистр или непосредственное значение. В команде допустимо использование как 16-битовых, так и 32-битовых операндов, но и первый, и второй операнды должны быть одного типа (за исключением случая, когда второй операнд — константа).
Пример 1
mov AX,00FFh ;Анализируемое данное
btc АХ, 5 ;AX=00DFh Бит 5 был = 1
;Сброс бита 5, ZF=1
Пример 2
mov AX,OOFFh /Анализируемое данное
btc АХ, 8 ;AX=lFFh Бит 8 был = О
;Установка бита 8, ZF=0
Пример 3
mov AX,8001h ;Анализируемое данное
mov BX,15 ;Номер проверяемого бита
btc AX,BX ;AX=0001h, ZF=1
Пример 4
; В полях данных
mem dw IFh
;В программном сегменте: ; Анализируемое данное
btc mem, I /mem=lEh, ZF=1
386+ BTR Проверка и сброс бита
Команда btr проверяет определенный бит в слове, заданном первым операндом, копирует его значение в флаг CF и сбрасывает. Номер бита выступает в качестве второго операнда. Первым операндом команды btr может служить регистр или ячейка памяти, вторым — регистр или непосредственное значение. В команде допустимо использование как 16-битовых, так и 32-битовых операндов, но и первый, и второй операнды должны быть одного типа (за исключением случая, когда второй операнд — константа).
Пример 1
mov AX,00Fh ;Анализируемое данное
btr АХ, 5 ;AX=00DFh. Бит 5 был = 1
;Сброс бита 5, ZF=1
Пример 2
mov AX,00FFh ;Анализируемое данное
btr AX, 8 ;AX=0FFh Бит 8 был =0
;Остался 0, ZF=0
Пример 3
mov AX,8001h ;Анализируемое данное
mov BX,15 ;Номер проверяемого бита
btr AX,BX ;AX=0001h Бит 15 был = 1
;Сброс бита 15, ZF=1
Пример 4
;В полях данных
mem dw IFh
;В программном сегменте: ;Анализируемое данное
btr mem,10 ;mem=lFh Бит 10 был = 0
;Остался 0, ZF=0
386+ BTS Проверка и установка бита
Команда bts проверяет определенный бит в слове, заданном первым операндом, копирует его значение в флаг CF и устанашшвает. Номер бита выступает в качестве второго операнда. Первым операндом команды bts может служить регистр или ячейка памяти, вторым — регистр или непосредственное значение. В команде допустимо использование как 16-битовых, так и 32-битовых операндов, но и первый, и второй операнды должны быть одного типа (за исключением случая, когда второй операнд — константа).
Пример 1
mov AX,OOFFh ;Анализируемое данное
bts AX, 5 ;AX=OOFFh Бит 5 был = 1
;Остался 1, ZF=1
Пример 2
mov AX,OOFFh ;Анализируемое данное
bts AX, 8 ;AX=lFFh Бит 8 был = О
;Установка бита 8, ZF=0
Пример 3
mov AX,8001h ; Анализируемое данное
mov BX,15 ;Номер проверяемого бита
bts AX,BX ;AX=8001h Бит 15 был = 1
;Остался 1, ZF=1
Пример 4
; В полях данных
mem dw IFh ; Анализируемое данное
;В программном сегменте:
bts mem,10 ;mem=4lFh Бит 10 был = О
; Установка бита 10, ZF=0
CALL Вызов подпрограммы
Команда call передает управление подпрограмме, сохранив перед этим в стеке смещение к точке возврата. Команда ret, которой обычно заканчивается подпрограмма, забирает из стека адрес возврата и возвращает управление на команду, следующую за командой call. Команда не воздействует на флаги процессора.
Команда call имеет четыре модификации:
— вызов прямой ближний (в пределах текущего программного сегмента);
— вызов прямой дальний (вызов подпрограммы, расположенной в другом программном сегменте);
— вызов косвенный ближний;
— вызов косвенный дальний.
Все разновидности вызовов имеют одну и ту же мнемонику call, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид вызова по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы:
near ptr — прямой ближний вызов;
far ptr — прямой дальний вызов;
word ptr — косвенный ближний вызов;
dword ptr — косвенный дачьний вызов.
Команда call прямого ближнего вызова заносит в стек относительный адрес точки возврата в текущем программном сегменте и модифицирует IP так, чтобы в нем содержатся относительный адрес точки перехода в том же программном сегменте. Необходимая для вычисления этого адреса величина смещения от точки возврата до точки перехода содержится в коде команды, который занимает 3 байт (код операции E8h и смещение к точке перехода).
Команда call прямого дальнего вызова заносит в стек два слова — сначала сегментный адрес текущего программного сегмента, а затем (выше, в слово с меньшим адресом) относительный адрес точки возврата в текущем программном сегменте. Далее модифицируются регистры IP и CS: в IP помещается относительный адрес точки перехода в том сегменте, куда осуществляется переход, а в CS — сегментный адрес этого сегмента. Обе эти величины берутся из кода команды, который занимает 5 байтов (код операции 9А1г, относительный адрес вызываемой подпрограммы и ее сегментный адрес).
Косвенные вызовы отличаются тем, что адрес перехода извлекается не из кода команды, а из ячеек памяти; в коде команды содержится информация о том, где находится адрес вызова. Длина кода команды зависит от используемого способа адресации.
Примеры прямого ближнего вызова
call near ptr subl ;Вызов подпрограммы subl
;из того же сегмента
call subl ;To же самое
Косвенные ближние вызовы
Пример 1
mov BX,offset subl ;ВХ=адрес подпрограммы
call BX ;Вызов подпрограммы
Пример 2
; В полях данных:
addr dw subl ;Ячейка с адресом подпрограммы
;В программном сегменте:
call DS:addr ;Вызов подпрограммы
call word ptr addr ;To же самое
Пример 3
;В полях данных:
addr dw subl ;Ячейка с адресом подпрограммы
;В программном сегменте:
mov SI,offset addr ;SI=адрес ячейки с адресом
;подпрограммы
call [SI] ;Вызов подпрограммы
Пример 4
;В полях данных:
tbl dw subl ;Ячейка с адресом
;подпрограммы 1
dw sub2 ;Ячейка с адресом
;подпрограммы 2
dw sub3 ;Ячейка с адресом
;подпрограммы 3
;В программном сегменте:
mov BX,offset tbl ;ВХ=адрес таблицы адресов
;подпрограмм
mov SI, 2 ;SI=смещение к адресу sub2
call [BX] [SI] ;Вызов подпрограммы 2
Пример прямого дальнего вызова
call far ptr subl ;Вызов подпрограммы sub2,
;расположенной в другом
;программном сегменте
Косвенные дальние вызовы
Пример 1
;В полях данных:
addr dd subl ;Поле с двухсловным
;адресом подпрограммы
;В программном сегменте:
call DS:addr ;Вызов подпрограммы
call dword ptr addr;To же самое
Пример 2
;В полях данных:
addr dd subl ;Поле с двухсловным
;адресом подпрограммы
;В программном сегменте:
mov DI,offset addr ;В1=адрес поля с адресом
;подпрограммы
call [DI] ;Вызов подпрограммы
Пример 3
; В полях данных:
tbl dd subl ;Адрес подпрограммы 1
dd sub2 ;Адрес подпрограммы 2
dd sub3 ;Адрес подпрограммы 3
;В программном сегменте:
mov SI,offset tbl ;DI=адрес таблицы адресов
mov DI,8 ;Смещение к адресу sub3
call [SI] [DI] ;Вызов подпрограммы sub3
386+ Допустимо использование дополнительных режимов адресации 32-разрядных процессоров.
В 32-разрядных приложениях допустимо использование 32-битовых операндов. В защищенном режиме роль сегментного адреса выполняет селектор.
Примеры
call [EAX] ;Косвенный вызов
call 8[ЕСХ] ;Косвенный вызов
CBW Преобразование байта в слово
Команда cbw заполняет регистр АН знаковым битом числа, находящегося в регистре AL, что дает возможность выполнять арифметические операции над исходным операндом-байтом, как над словом в регистре АХ. Команда не имеет параметров и не воздействует на флаги процессора.
Пример 1 mov AL,5
cdw ;AX=0005h
Пример 2
mov AL, - 2 ;AL=FEh=-2 (байт)
cdv ;AX=FFFEh=-2 (слово)
386+ CDQ Преобразование двойного слова в четверное
Команда cdq расширяет знак двойного слова в регистре ЕАХ на регистр EDX. Эту команду можно использовать для образования четырсхсловного делимого из двухсловного перед операцией двухсловного деления. Команда не имеет параметров и не воздействует на флаги процессора.
Пример 1
;В полях данных
mem dd -2 ; Отрицательное число
;В программном сегменте
mov ЕАХ,mem ;EAX=FFFFFFFEh
cdq ;EDX=FFFFFFFFh, EAX=FFFFFFFEh
Пример 2
;В полях данных
mem dd 7FFFFFFEh ,'Положительное число
;В программном сегменте
mov ЕАХ,mem ;EAX=7FFFFFFEh
cdq ;EDX=00000000h, EAX=7FFFFFFEh
CLC Сброс флага переноса
Команда clc сбрасывает флаг переноса CF в регистре флагов. Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
clc ;CF=0, независимо от
;исходного состояния
CLD Сброс флага направления
Команда eld сбрасывает флаг направления DF в регистре флагов, устанавливая прямое (в порядке возрастания адресов) направление выполнения операций со строками (цепочками). Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
cld ;DF=0, независимо от
;исходного состояния
CL1 Сброс флага прерываний
Команда sti сбрасывает флаг разрешения прерываний IF в регистре флагов, запрещая (до установки этого флага командой sti) все аппаратные прерывания (от таймера, клавиатуры, дисков и т.д.) Команда не запрещает процессору выполнение команды hit (реализация программных прерываний); также не запрещаются немаскируемые прерывания, поступающие на вход NMI микропроцессора. Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
cli ;IF=0, независимо от
;исходного состояния
386Р+ CLTS Сброс флага переключения задачи в управляющем регистре 0
Команда cits сбрасывает флаг TS в регистре CR0.
CMC Инвертирование флага переноса
Команда сmс изменяет значение флага переноса CF в регистре флагов на обратное. Команда не имеет операндов и не воздействует на остальные флаги процессора.
Пример
cmc ;Состояние флага CF
;изменяется на обратное
СМР Сравнение
Сами операнды не изменяются. Таким образом, если команду сравнения записать в общем виде
стр операнд_1, операнд_2
то ее действие можно условно изобразить следующим образом:
операнд_1 — операнд_2 -> флаги процессора
В качестве первого операнда команды сmр можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно, как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Обычно вслед за командой сmр стоит одна из команд условных переходов, анализирующих состояние флагов процес
сора. При сравнении чисел без знака необходимо использовать команды условных переходов, предназначенные для анализа чисел без знака (ja, jb и проч.). При сравнении чисел со знаком необходимо использовать команды условных переходов, предназначенные для анализа чисел со знаком (jl, jg и проч.).
Пример 1
cmp АХ,10000 ;АХ-10000
je eqlOOOO ;Переход на метку eqlOOOO,
;если АХ=10000
Пример 2
;В полях данных:
base dw 8002h
;В программном сегменте:
cmp DX,base DX-base
jb below ;Переход на метку below,
;если DX, рассматриваемое
;как число без знака, меньше
;числа без знака 8002h=32770
Пример 3
;В полях данных:
base dw 8002h
;В программном сегменте:
cmp DX,base DX-base
jl less ;Переход на метку less, если
;DX, рассматриваемое как
;число со знаком, меньше
;числа со знаком 8002h=-32766
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
cmp EAX,8000000 Oh
ja above ;Переход, если
;EAX=80000001h…FFFFFFFFh
CMPSB Сравнение строк по байтам
CMPSW Сравнение строк по словам
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они сравнивают по одному элементу каждой строки, фактически осуществляя вычитание второго операнда из первого и устанавливая в соответствии с результатом вычитания флаги CF, PF, AF, ZF, SF и OF. Команда cmpsb выполняет сравнение по байтам, команда cmpsw — по словам, а команда cmps может быть использована для сравнения как байтов, так и слов. В последнем случае размер сравниваемых элементов определяется их описанием (с помощью директив db или dw). Первый операнд адресуется через DS:SI, второй — через ES:DI. Таким образом, операцию сравнения можно условно изобразить следующим образом:
(DS:SI) — (ES:DI) -> флаги процессора
После каждой операции сравнения регистры SI и DI получают положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1 или 2 в зависимости от размера сравниваемых элементов (байт или слово).
Вариант команды cmps имеет формат
cmps строка_1, строка_2
(что не избавляет от необходимости инициализировать регистры DS:SI и ES:DI адресами строк строка_1 и строка_2 соответственно). В этом формате возможна замена сегмента первой строки:
cmps ES:строка_ 1, строка_2
Рассматриваемые команды могут предваряться префиксами повторения repe/repz (повторять, пока элементы равны, т.е. до первого неравенства) и repne/repiiz (повторять, пока элементы не равны, т.е. до первого равенства). В любом случае выполняется не более СХ операций над последовательными элементами.
После выполнения рассматриваемых команд регистры SI и DI указывают на ячейки памяти, находящиеся за теми (если DF=0) или перед теми (если DF=1) элементами строк, на которых закончились операции сравнения.
Пример 1
;В полях данных сегмента данных, адресуемого через DS:
strl db 'FILE.001' ;1-я строка
;В полях данных сегмента данных, адресуемого через ES:
str2 db 'FILE.012' ;2-я строка
;В программном сегменте:
eld ;Сравнение вперед
mov SI,offset strl ;DS:SI ® strl
mov DI, off set str2 ;ES:DI ® str2
mov CX,8 ;Длина сравниваемых строк
repe cmpsb ;Поиск различия в строках
je equal ;Переход, если строки
;совпадают
notequ: ;Продолжение, если строки
;не совпадают
В примере 1 строки не совпадают, и команда je выполнена не будет. После завершения сравнения строк управление будет передано на метку notequ. Содержимое регистров в этой точке: СХ=1 (так как не выполнено сравнение одной последней пары символов), SI = <смещение strl> + 7, DI = <смещение strl> + 7 (выполнено сравнение 7 пар символов).
Пример 2
;В полях данных сегмента данных, адресуемого через DS:
strl db '12345678*90' ;1-я строка
;В полях данных сегмента данных, адресуемого через ES:
str2 db ' abcdefgh*ij' ;2-я строка
; В программном сегменте:
cld ;Сравнение вперед
mov SI,offset strl;DS:SI ' strl
mov DI,offset str2;ES:DI ' str2
mov CX,11 ;Длина сравниваемых строк
repne cmpsb ;Поиск первой пары
;одинаковых элементов
jne notequ ;Переход, если таковой нет
found: ;Продолжение, если пара
;одинаковых элементов найдена
В примере 2 имеется пара одинаковых элементов (*) в позиции 8 от начата строк. Поэтому команда jne выполнена не будет. После завершения сравнения строк управление будет передано на метку found. Содержимое регистров в этой точке: СХ=2 (так как не выполнено сравнение двух последних пар символов), SI = <смещенис strl> + 9, DI = <смешенис strl> + 9 (выполнено сравнение 9 пар символов).
Пример 3
;В полях данных сегмента, адресуемого через ES:
strl db '09.12.1998' ;1-я строка
str2 db '09.12.1998' ;2-я строка
;В программном сегменте:
eld ;Сравнение вперед
mov SI, off set strl ;DS:SI -> strl
mov DI,offset str2 ;ES:DI -> str2
mov CX,10 ;Длина сравниваемых строк
repe cmps ES:str1,ES:str2 ;Поиск различия в строках
je equal ; Переход, если строки
;одинаковы
notequal: ;Продолжение, строки
;различаются
В примере 3 строки одинаковы и после завершения сравнения управление будет передано на метку equal. Поскольку строки описаны с помощью директив db, фактически выполняется команда cmpsb, т.е. побайто вое сравнение.
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
386+ CMPSD Сравнение строк по двойным словам
Команда аналогична командам МП 86 cmpsb и cmpsw, но позволяет сравнивать 32-битовые участки строк, адресуемых через регистры DS:ESI и ES:EDI (или, в 16-разрядных приложениях, через DS:SI и ES:DI). Использование мнемоники cinpsd с префиксом rep не означает, что в качестве счетчика будет автоматически использоваться расширенный регистр ЕСХ.
Пример
;В полях данных сегмента, адресуемого через DS
areal dd 152345,168666,954333
area2 dd 152345,168666,954331
;B программном сегменте
push DS
pop ES ;ES=DS
mov SI,offset areal ;DS:SI ->areal
mov DI,offset area2 ;ES:DI ->area2
mov CX,3 ;Будем сравнивать З числа
repe cmpsd
je equal
В приведенном примере в строках (фактически это целочисленные массивы) различаются последние элементы, и команды jc выполнена не будет.
486+ CMPXCHG Сравнение и обмен
Команда cmpxchg выполняет в одной операции сравнение и обмен операндов. Команда требует два параметра и неявным образом использует третий операнд — регистр ЕАХ. Первый операнд (приемник) должен находиться в 16- или 32-битовой ячейке памяти, второй операнд (источник) — в регистре общего назначения такого же размера. Команда выполняет сравнение операнда-приемника с содержимым неявного операнда — регистра ЕАХ. Если сравниваемые значения совпадают, операнд-приемник замещается операндом-источником (т.е. содержимое регистра записывается в память). Если сравниваемые значения не совпадают, содержимое памяти (приемник) поступает в регистр ЕАХ (рис. П1). Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
; В полях данных
mem dw 135
; В программном сегменте
mov AX,135
mov BX,60
cmpxchg mem,BX ;mem=AX. Регистр ® память ;
mem=60, BX=60, АХ=135
Пример 2
; В полях данных
mem dw 135
;В программном сегменте
mov AX,148
mov BX,60
cmpxchg mem,BX ;mem<>AX. Память ® АХ
;mem=135, BX=60, AX=148
Pentium+ CMPXCHG8B Сравнение и обмен 8 байтов
Команда cmpxchgSb выполняет в одной операции сравнение и обмен 8-байтовых операндов. Команда требует один параметр и неявным образом использует еще два операнда — пары регистров EDX:EAX и ЕСХ:ЕВХ. В качестве явного операнда команды (приемника) может выступать только 64-битная (8-байтовая) ячейка памяти. Команда выполняет сравнение операнда-приемника в памяти с содержимым EDX:EAX. Если сравниваемые значения совпадают, то операнд-приемник в памяти замещается 64-битным значением ЕСХ:ЕВХ. Если сравниваемые значения не совпадают, содержимое памяти поступает в пару регистров EDXrEAX, замещая один из сравниваемых операндов (рис. П2). Команда воздействует на флаг ZF.
Пример 1
; В полях данных
mem dq 1122334455667788h
;В программном сегменте
mov ЕСХ,9
mov ЕВХ,5
mov EDX,11223344h
mov EAX,55667788h
cmpxchgSb mem ;mem=EDX:EAX. ECX:EBX ® mem ;
mem=0000000900000005h
Пример 2
; В полях данных
mem dq 1122334455667788h
;B программном сегменте
mov ECX,9
mov EBX,5
mov EDX,11223344h
mov EAX,55667789h
cmpxchgSb mem ;memOEDX: EAX. Mem -" EDX : EAX ;mem=1122334455667788h ;EDX=11223344h, EAX=55667788h
При работе с многобайтовыми данными не следует забывать о том, что в памяти байты любых данных всегда выстраиваются в порядке их номеров,т.е. от младшим к все более старшим, в то время как при изображении чисел мы применяем обратный порядок — сначала пишем старшие разряды числа, затем младшие. В то же время символьные строки мы изображаем так же, как они располагаются в памяти — для нас естественно считать, что по мере движения по строке вправо номер символа возрастает.
Пример 3
; В полях данных
meml db '12345678' ;Строка-операнд
mem2 db '12345678' ;Сравниваемая строка
;В программном сегменте
mov ECX,68676665h ;'efgh'
mov EBX,64636261h ;'abcd'
mov EDX,dword ptr mem2+4 ;Забираем старшую
;часть строки
mov EAX,dword ptr mem2 ;Забираем младшую
;часть строки
cmpxchg8b gword ptr meml ;Операнды совпадают
;ZF=1, mem1=''abcdefgh''
;ECX:EBX без изменений
;EDX:EAX без изменений
Пример 4
;В полях данных
meml db '12345678' ;Строка-операнд
mem2 db 'abcdefgh' ;Сравниваемая строка
; В программном сегменте
mov ECX,68676665h ;'efgh'
mov EBX,64636261h ;'abed'
mov EDX,dword ptr mem2+4 ;3абираем старшую
;часть строки
mov EAX,dword ptr mem2 ;Забираем младшую
;часть строки
cmpxchg8b qword ptm mem1 ;Операнды не совпадают
;ZF=0, EDX=38373635='5678'
;EAX=34333231='1234'
;mem1s без изменения
;При неравенстве ЕСХ:ЕВХ не принимают участие в операции
Pentium+ CPUID Идентификация процессора
Команда cpuid позволяет получить код идентификации процессора, установленного на данном компьютере. Команда в качестве неявного операнда использует регистр ЕАХ. Для процессоров Pentium регистр ЕАХ перед вызовом команды cpuid может принимать два значения: 0 и 1. Если ЕАХ=0, то команда возвращает в регистре ЕАХ код 1, а в регистрах ЕВХ, EDX и ЕСХ (именно в таком порядке) — три части символьной строки, идентифицирующей изготовителя процессора. Для процессоров Intel возвращаемая строка в целом имеет вид «Genumclatcl».
Если перед вызовом команды cpuid значение ЕАХ равно 1, то команда возвращает в регистре ЕАХ коды разработки конкретной версии процессора, а в регистре EDX код IBFli, содержащий информацию о возможностях процессора.
Коды разработки в регистре ЕАХ хранятся в следующем формате:
биты 0 … 3 — номер поколения (например, 3);
биты 4 … 7 — модель (например, 4);
биты 8 … 11 — семейство (5 для Pentium).
Содержимое регистра EDX включает конфиденциальную информацию изготовителя, а также говорит о наличии на кристалле микропроцессора арифметического сопроцессора (бит 0) и поддержке команды cmpxchgSb (бит 8).
Пример
;В полях данных mem dd 0,0,0 ;В программном сегменте
mov ЕАХ,О
cpuid ;EAX=0001h
mov mem, ЕВХ
mov mem+4, EDX
mov mem+8, ECX ;mem=’Genuinelntel’
cpuid EAX=543h (например) ,EDX = lBFh
CWD Преобразование слова в двойное слово
Команда cwd заполняет регистр DX знаковым битом содержимого регистра АХ, преобразуя тем самым 16-разрядное число со знаком в 32-разрядное, размещаемое в регистрах DX:AX. Команду удобно использовать для преобразования двухбайтового делимого в четырсхбайтовое (двойное слово) при делении на 16-разрядный операнд. Команда не имеет параметров и не воздействует на флаги процессора.
Пример 1
mov AX,32767 ;AX=7FFFh
cwd ;AX=7FFFh, DX=OOOOh.
;DX:AX=32767
Пример 2
mov AX,-32768 ;AX=8000h
cwd ;AX=8000h, DX=FFFFh.
;DX:AX=-32768
386+ CWDE Преобразование слова в двойное слово с расширением
Команда cwde заполняет старшую половину регистра ЕАХ знаковым битом содержимого регистра АХ, преобразуя тем самым 16-разрядное число со знаком в 32-разрядное, размещаемое в расширенном регистре ЕАХ. Команда не имеет операндов и не воздействует на флаги процессора.
Пример
; В полях данных
mem dw - 3
;В программном сегменте
mov AX,mem ;AX=FFFD
cwde ;EAX=FFFFFFFDh
DAA Десятичная коррекция в регистре AL после сложения
Команда daa корректирует результат сложения в регистре AL двух упакованных двоично-десятичных (BCD) чисел (по одной цифре в каждом полубайте), чтобы получить пару правильных упакованных двоично-десятичных цифр. Команда используется вслед за операцией сложения упакованных двоично-десятичных чисел. Если результат сложения превышает 99, возникает перенос и устанавливается флаг CF. Команда воздействует на флаги SF, ZF, AF, PF и C
Пример 1
mov AL,87h ;Упакованное BCD 87
add AL,04h ;После сложения AL=8Bh
daa ;AL=91h, т.е. упакованное BCD 91
Пример 2
mov AL,87h ;Упакованное BCD 87
add AL,11h ;После сложения AL=97h
daa ;AL=97h, т.е. упакованное
;BCD 97 (в данном случае
;команда daa ничего не делает)
DAS Десятичная коррекция в регистре AL после вычитания
Команда das корректирует результат вычитания в регистре AL двух упакованных двоично-десятичных (BCD) чисел (по одной цифре в каждом полубайте), чтобы получить пару правильных упакованных десятичных цифр. Команда используется вслед за операцией вычитания упакованных двоично-десятичных чисел. Если для вычитания требовался заем, устанавливается флаг CF. Команда воздействует на флаги SF, ZF, AF, PF и CF.
Пример 1
mov AL,55h ;Упакованное BCD 55
sub AL,19h ;После вычитания AL=3Ch
das ;AL=36h, т.е. упакованное BCD 36
Пример 2
mov AL,55h ;Упакованное BCD 55
sub AL,15h ;После вычитания AL=40h
das ;AL=40h, т.е. упакованное
;BCD 40 (в данном случае
;команда das ничего не делает)
DEC Декремент (уменьшение на 1)
Команда dec вычитает 1 из операнда, в качестве которого можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Операнд интерпретируется как число без знака. Команда воздействует на флаги OF, SF, ZF, AF и PF.
Пример 1
mov AX,0FFFFh
dec AX ;AX=FFFEh
Пример 2
mov CX,0
dec CX ;CX=FFFFh
Пример 3
mov CX,3500h
dec CL ;CX=35FFh
Пример 4
; В полях данных
mem dw 68
;B программном сегменте
dec mem mem=67
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov EAX, 0
dec EAX ;EAX=FFFFFFFFh
DIV Деление целых чисел без знака
Команда div выполняет деление целого числа без знака, находящегося в регистрах АХ (в случае деления на байт) или DX:AX (в случае деления на слово), на операнд-источник (целое число без знака). Размер делимого в два раза больше размеров делителя и остатка.
Для однобайтовых операций делимое помещается в регистр АХ; после выполнения операции частное записывается в регистр AL, остаток — в регистр АН.
Для двухбайтовых операций делимое помещается в регистры DX:AX (в DX — старшая часть, в АХ — младшая); после выполнения операции частное записывается в регистр АХ, остаток — в регистр DX.
В качестве операнда-делителя команды div можно указывать регистр (кроме сегментного) или ячейку памяти; не допускается деление на непосредственное значение. Если делитель равен 0, или если частное не помещается в назначенный регистр, возбуждается прерывание с вектором 0. Команда не воздействует на флаги процессора.
Команду div можно использовать для целочисленного деления неупакованного двоично-десятичного числа в регистре АХ не неупакованный двоично-десятичный делитель, если перед ней выполнить команду aad (см. пример 3).
Пример 1
mov AX,506 ;Делимое
mov BL,50 ;Делитель
div BL ;AL=0Ah (частное), AH=06h (остаток)
Пример 2
; В полях данных
long dd 65537 ;Делимое
;В программном сегменте
mov DX,word ptr long+2 ;DX=0001h, старшая
;часть делимого
mov AX,word ptr long ;AX=0001h, младшая
;часть делимого
mov CX,256 ;Делитель
div CX ;AX=0100h (частное),
;DX=0001h (остаток)
Пример З
mov AX,0807h ;Неупакованное BCD 87
mov DL,09h ;Неупакованное BCD 9
aad ;AX=0057h=87
div DL ;AX=0609h, т.е. 9 и 6 в остатке
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. При этом, если делитель представляет 32-битовую величину, то возможен только один вариант команды деления, когда делимое находится в парс регистров EDX:EAX. В этом случае частное будет помещено в регистр ЕАХ, остаток — в EDX.
Пример
mov ЕАХ, 0FFFFFFFh ;Младшая часть делимого
mov EDX,0 ;Старшая часть делимого
mov EBX,256 ;Делитель
div EBX ;Частное в EAX=000FFFFFh,
;Остаток в EDX=000000FFh
386+ ENTER Создание стекового кадра для параметров процедуры
Команда enter, обычно являющаяся первой командой процедуры, выделяет заданный объем стекового пространства для локальных (автоматических) параметров процедуры, предоставляя процедуре указатель на выделенную область (в качестве такого указателя используется регистр ЕВР) и смещая указатель стека ESP так, чтобы он указывал на начало свободного стекового пространства. В результате процедура имеет возможность обращаться по ходу своего выполнения к своим локальным параметрам и, в то же время, пользоваться оставшимся пространством стека для временного сохранения в нем любых данных с помощью команд push и pop. Команда leave в конце процедуры выполняет обратные действия, возвращая стек в исходное состояние и уничтожая область локальных переменных. Локальными, как известно, называются как раз те переменные, которые существуют только в течение времени выполнения некоторой процедуры, и автоматически исчезают после се завершения.
Команды enter и leave используются многими языками высокого уровня для управления доступом к локальным переменным вложенных процедур.
Команда enter имеет два операнда. Первый (16-битовое непосредственное значение) определяет число байтов, выделяемых в стеке для локальных переменных. Для 32-разрядных приложений место в стеке выделяется двойными словами (по 4 байт), для 16-разрядных — словами (по 2 байт). Второй операнд (8-битовос непосредственное значение) задаст так называемый лексический уровень процедуры, характеризующий степень ее вложенности. В зависимости от значения лексического уровня, команда enter выполняется по-разному. При лексическом уровне, равном 0, реа-лизуется невложенная форма команды enter. В этом случае после входа в процедуру (командой call) с сохранением в стеке адреса возврата, в стек заносится текущее содержимое регистра ЕВР, в ЕВР копируется текущее значение указателя стека, а указатель стека смещается на число байтов, заданное первым операндом команды enter (рис. ПЗ). Создаваемая на сте-ке структура носит название стекового кадра, а регистр ЕВР выполняет в данном случае функцию указателя стекового кадра.
Подпрограмма имеет возможность обращаться к своим локальным переменным по адресам ESP-4 и ESP-8 (для случая резервирования места под две переменные). Занеся в стек по этим адресам некоторые данные (полученные в качестве параметров вызова через регистры общего назначения или созданные самостоятельно) подпрограмма может затем многократно к ним обращаться, не боясь их затирания в процессе использования стека. Поскольку команда enter настроила указатель стека на область, находящуюся за пределами локальных переменных, программа может использовать команды push для сохранения в стеке временных данных.
Команда leave, размещаемая в самом конце процедуры, перед завершающей командой ret, копирует содержимое ЕВР в ESP, освобождая (в логическом плане) область локальных переменных, и снимает со стека сохраненное там исходное содержимое ЕВР. После этого командой ret можно вернуться в вызывающую процедуру.
Поскольку первый параметр команды enter имеет размерность слова, процедура в принципе имеет возможность зарезервировать в стеке для своих локальных переменных до 64 Кбайт стекового пространства.
Лексические уровни, отличные от 0, используются в тех случаях, когда по правилам языка высокого уровня каждая вложенная процедура имеет право обращаться к локальным переменным всех вышележащих процедур, но не к процедурам, находящимся на параллельных с ней ветвях вложенности. Другими словами, область видимости переменных распространяется на все вложенные процедуры, но две подпрограммы, вызываемые из одной и той же (вышележащей) процедуры, «не видят» друг друга.
В таких случаях главной процедуре назначается лексический уровень 1, все вызываемые из нее подпрограммы получают значение лексического уровня 2, подпрограммы, вызываемые из этих процедур, имеют уровень 3 и т.д. Команды enter при ненулевом значения второго параметра создают в стеке стековые кадры с более сложной структурой. Отличие такого стекового кадра от рассмотренного выше заключается в том, что в него, помимо области локальных переменных, входят также указатели стековых кадров всех вышележащих процедур. В результате любая подпрограмма может с помощью своего указателя (т.е. содержимого ESP) обратиться к собственных! переменным, а используя хранящиеся в стеке указатели кадров вышележащих процедур, «дотянуться» и до их локальных переменных. По-прежнему команды leave освобождают стек от стековых кадров вместе со всеми находящимися в них данными.
Пример
;Вызывающая процедура
call subrl
;Подпрограмма subrl
subrl proc
enter2048,0 ;Место под локальные данные
. . . ;Работа с локальными данными
leave
ret
HLT Останов
Команда hlt прекращает выполнение программы и переводит процессор в состояние останова. Работа процессора возобновляется после операции запуска, а также в случае прихода немаскируемого или разрешенного маскируемого прерываний.
IDIV Деление целых чисел со знаком
Команда IDIV выполняет деление целого числа со знаком, находящегося в регистрах АХ (в случае деления на байт) или DX:AX (в случае деления на слово), на операнд-источник (целое число со знаком). Размер делимого в два раза больше размеров делителя и остатка. Оба результата рассматриваются как числа со знаком, причем знак остатка равен знаку делимого.
Для однобайтовых операций делимое помещается в регистр АХ; после выполнения операции деления частное записывается в регистр AL, остаток — в регистр АН.
Для двухбайтовых операций делимое помещается в регистры DX:AX (в DX — старшая часть, в АХ — младшая); после выполнения операции деления частное записывается в регистр АХ, остаток — в регистр DX.
В качестве операнда-делителя команды idiv можно указывать регистр данных или ячейку памяти; не допускается деление на непосредственное значение. Если делитель равен 0, или если частное не помещается в назначенный регистр, возбуждается прерывание через вектор 0. Команда не воздействует на флаги процессора.
Пример 1
mov AX,506 ;Делимое
mov BL,50 ;Делитель
idiv BL ;AL=0Ah (частное), AH=06h
; (остаток)
Пример 2
;В полях данных
long dd 0F0007h ;Делимое
; В программном сегменте
mov DX,word ptr long+2;DX=000Fh, старшая
;часть делимого
mov AX,word ptr long;AX=0007h, младшая
;часть делимого
mov CX,256 ;Делитель
idiv СХ ;AX=0F00h (частное),
;DX=0007h (остаток)
Пример 3
mov AX,-506 ;AX=FE06h, делимое
mov BL,50 ;Делитель
idiv BL ;AL=F6h (-10), AH=FAh (-6)
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. При этом, если делитель представляет 32-битовую величину, то возможен только один вариант команды деления, когда делимое находится в парс регистров EDX:EAX. В этом случае частное будет помещено в регистр БАХ, остаток — в EDX.
Пример
; В полях данных
dvd dq -100001 Делимое
;B программном сегменте
mov EAX,dword ptr dvd EAX=FFFE795Fh
;(младшая часть делимого)
mov EDX,dword ptr dvd+4 EDX=FFFFFFFFh (старшая
;часть делимого)
mov EBX,50 Делитель
idiv EBX Частное в EAX=FFFFF830h=
;-2000, остаток в EDX=FFFFFFFFh=-1
IMUL Умножение целых чисел со знаком
Команда IMUL выполняет умножение целого числа со знаком, находящегося в регистре AL (в случае умножения на байт) или АХ (в случае умножения на слово), на операнд-источник (целое число со знаком). Размер произведения в два раза больше размера сомножителей.
Для однобайтовых операций один из сомножителей помещается в регистр AL; после выполнения операции произведение записывается в регистр АХ.
Для двухбайтовых операций один из сомножителей помещается в регистр АХ; после выполнения операции произведение записывается в регистры DX:AX (в DX — старшая часть, в АХ — младшая).
В качестве операнда-сомножителя команды imul можно указывать регистр (кроме сегментного) или ячейку памяти; не допускается умножение на непосредственное значение. Команда воздействует на флаги OF и CF. Если АН или DX представляют собой просто знаковое расширение AL или АХ, соответственно (т.е. результат умножения со знаком верен), OF и CF сбрасываются в 0; в противном случае (результат со знаком не помещается в АХ или DX:AX) OF и CF устанавливаются в 1.
Пример 1
mov AL,5 ;Первый сомножитель
mov BL,3 ;Второй сомножитель
imul BL ;AX=000Fh (произведение)
Пример 2
mov AX,256 ;Первый сомножитель
mov BX,256 ;Второй сомножитель
imul BX ;DX=0001h, AX=0000h
;(число 65536)
Пример 3
mov AL,-5 ;AL=FBh
mov BL,3 ;BL=03h
imul BL ;AX-‘FFF1h (-15)
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. Имеются также варианты команды с двумя и тремя операндами.
Для команды imul с одним операндом второй сомножитель должен располагаться в AL, АХ или ЕАХ. Процессор выбирает размерность второго сомножителя, исходя из размерности первого, указанного в качестве операнда. 16-, 32- или 64-битовый знаковый результат помещается в регистры АХ, DX:AX или EDX:EAX, соответственно. Если после операции умножения содержимое АН, DX или EDX является лишь знаковым расширением AL, АХ или ЕАХ, соответственно, то флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.
Для команды imul с двумя операндами их произведение записывается в первый операнд; второй операнд не изменяется. В качестве первого операнда могут выступать 16- или 32-разрядные регистры общего назначения; в качестве второго операнда — 16- или 32-разрядные регистры общего назначения, 16- или 32-битовые ячейки памяти или непосредственное значение. Оба операнда должны иметь один размер. Если результат умножения помещается в первый операнд, флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.
Для команды imul с тремя операндами произведение второго и третьего операндов записывается в первый операнд. В качестве первого операнда могут выступать 16- или 32-разрядные регистры общего назначения; в качестве второго операнда — 16- или 32-разрядные регистры общего назначения или 16- или 32-битовые ячейки памяти; в качестве третьего операнда — только непосредственное значение. Два первых операнда должны иметь один размер. Если результат умножения помещается в первый операнд, флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.
Пример 1
mov EAX,-1 ;Первый сомножитель
mov ESI,100000000 ;Второй сомножитель
imul ESI ;EDX=FFFFFFFFh,
;EAX=FA0AlF00h
;Результат=-100000000
Пример 2
;В полях данных
ор2 dd 100h ;Первый сомножитель
; В программном сегменте
mov EAX,400000h ;Второй сомножитель
imul EAX,op2 ;EAX=40000000h
Пример 3
mov BX,300h
imul АХ,ВХ,4 ;AX=300h*4=0C00h
IN Ввод из порта
Команда in вводит в регистр AL или АХ соответственно байт или слово из порта, указываемого вторым операндом. Адрес порта помещается в регистр DX. Если адрес порта не превышает 255, он может быть указан непосредственным значением. Указание регистра-приемника (AL или АХ) обязательно, хотя с другими регистрами команда in не работает, и их указывать нельзя. Команда не воздействует на флаги процессора.
Пример 1
in AL, 60h ;Ввод байта из порта 60h
Пример 2
mov DX,3D5h ;Адрес порта
in AL,DX ;Ввод байта из порта 3D5h
386+ Допустимо использование в качестве операнда-приемника расширенного регистра ЕАХ (если адресуемое устройство позволяет прочитать из его порта двойное слово).
Пример
mov DX,345h ;Адрес порта
in EAX,DX
INC Инкремент (увеличение на 1)
Команда inc прибавляет 1 к операнду, в качестве которого можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Операнд интерпретируется как число без знака. Команда воздействует на флаги OF, SF, ZF, AF и PF. Команда не воздействует на флаг CF; если требуется воздействие на этот флаг, необходимо использовать команду add op,l.
Пример 1
mov AX,0563h
inc AX ;AX=0564h
Пример 2
mov BH,15h
inc BH ;BH=16h
Пример 3
mov AX,A5FFh
inc AL ;AX=A500h
inc AH ;AX=A600h
Пример 4
mov AX,0FFFFh
inc AX ;AX=0000h, ZF=1, CF=0
;Для сравнения:
mov CX,0FFFFh
add CX,1 ;CX=0000h, ZF=1, CF=1
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
;В полях данных
mem dd 12345678h
; В программном сегменте
inc mem ;mem=12345679h
386+ INS Ввод строки из порта
Команды предназначены для ввода данных из порта непосредственно в память. Адрес порта указывается, как и для команды in, в регистре DX, при этом задание адреса порта непосредственным значением не допускается. Данные пересылаются по адресу, находящемуся в паре регистров ES:EDI. Замена сегмента не допускается. Команда insb переносит из порта 1 байт, команда insw — 1 слово, команда insd — 1 двойное слово, а команда ins может быть использована для передачи байтов, слов и двойных слов. В последнем случае размер загружаемого данного определяется описанием строки (с помощью директив db, dw или dd). После передачи данных регистр EDI получает положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1, 2 или 4, в зависимости от размера передаваемых данных. Вариант команды ins имеет формат
ins строка, DX
(что не избавляет от необходимости инициализировать регистры ES:EDI адресом строки).
Если устройство, адресуемое через порт, может передавать последовательность данных, то команды ins можно предварить префиксом повторения rep. В этом случае из порта принимается СХ элементов данных заданного размера.
Команды ins не воздействуют на флаги процессора.
Пример
;В сегменте данных, адресуемых через DS
mem dw 0
;В программном сегменте
push DS
pop ES ;ES=DS
mov DI,offset mem;ES:DI -> mem
mov DX,303h ;Адрес порта
insw ;Ввод из порта 16-битового данного
INT Программное прерывание
Команда hit инициирует в процессоре процедуру прерывания, в результате которой управление передается на обработчик прерывания с номером n, который указан в качестве операнда команды int. В стек текущей программы заносится содержимое регистра флагов, сегментного регистра CS и указателя команд IP, после чего в регистры IP и CS передается содержимое двух слов из вектора прерывания с номером n (расположенных по адресам 0:n*4 и 0:n*4+2). Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.
Пример 1
int 60h ;Переход на прикладной
;обработчик прерывания 60h
Пример 2
mov AH,1 ;Функция MS-DOS — ввод с
;клавиатуры кода ASCII символа
int 2h ;Вызов MS-DOS
Пример 3
mov АН, 0 ;Функция BIOS (прерывание
;16h) — ввод с клавиатуры
;кода ASCII и скен-кода символа
int 16h ;Вызов BIOS
INTO Прерывание по переполнению
Команда into, будучи установлена вслед за какой-либо арифметической, логической или строковой командой, вызывает обработчик прерываний через вектор 4, если предшествующая команда установила флаг переполнения OF. Перед использованием команды INTO прикладной программист должен поместить в вектор прерывания 4 двухсловный адрес своей программы обработки прерывания по переполнению. Команда сбрасывает флаги IF и TF в 0. Команда iret, которой всегда завершается обработчик прерывания, восстанавливает исходное состояние этих флагов.
Пример
add AX,BX ;Произвольная команда
into ;Вызов прикладного
;обработчика через вектор 4,
;если OF=1
… ;Продолжение программы, если OF=0
IRET Возврат из прерывания
Команда iret возвращает управление прерванному в результате аппаратного или программного прерывания процессу. Команда извлекает из стека три верхние слова и помещает их в регистры IP, CS и флагов (см. команду int). Командой iret должен завершаться любой обработчик прерываний, как аппаратных, так и программных (от команды int). Команда не воздействует на флаги, однако она загружает в регистр флагов из стека его исходное содержимое, которое было там сохранено процессором в процессе обслуживания прерывания. Если требуется, чтобы после возврата из обработчика программного прерывания командой iret какие-либо флаги процессора были установлены требуемым образом (весьма распространенный прием), их установку надо выполнить в копии флагов в стеке.
386+ IRETD
Возврат из прерывания в 32-разрядном режиме
Команда iretd используется в защищенном режиме для возврата из обработчика прерывания или исключения, а также для переключения на исходную задачу. В отличие от 16-разрядной команды iret, данная команда, завершая обработку прерывания или исключения, снимает со стека 3 двойных слова, содержащие расширенный регистр флагов EFALGS, CS и расширенный указатель команд EIP. В случае переключения задач команда iretd выполняет переключение контекстов задач — сохранение состояния завершающейся задачи в ее сегменте состояния задачи и загрузку регистров процессора из сегмента состояния исходной задачи.
Jcc Команды условных переходов
Команды, обозначаемые (в книгах, не в программах!) Jcc, осуществляют переход по указанному адресу при выполнении условия, заданного мнемоникой команды. Если заданное условие не выполняется, переход не осуществляется, а выполняется команда, следующая за командой Jcc. Переход может осуществляться как вперед, так и назад в диапазоне + 127…-128 байтов.
В составе команд процессора предусмотрены следующие команды условных переходов:
Команда Перейти, если Условие перехода
ja выше CF=0 и ZF=0
jae выше или равно CF=0
jb ниже CF=1
jbe ниже или равно CF=1 или ZF=1
jc перенос CF=1
jcxz CX=0 CX=0
je равно ZF=1
jg больше ZF=0 или SF=OF
jge больше или равно SF=OF
jl меньше SF не равно OF
jle меньше или равно ZF=1 или SF не равно OF
jna не выше CF=1 или ZF=1
jnae не выше и не равно CF=1
jnb не ниже CF=0
jnbe не ниже и не равно CF=0 и ZF=0
jnc нет переноса CF=0
jne не равно ZF=0
jng не больше ZF=1 или SF не равно OF
jnge не больше и не равно SF не равно OF
jnl не меньше SF=OF
jnle не меньше и не равно ZF=0 и SF=OF
jno нет переполнения OF=0
jnp нет четности PF=0
jns знаковый бит равен О SF=0
jnz не нуль ZF=0
jo переполнение OF=1
jp есть четность PF=1
jpe сумма битов четная PF=1
jpo сумма битов нечетная PF=0
js знаковый бит равен SF=1
jz нуль ZF= I
Команды условных переходов, осуществляющие переход по условию «выше — ниже», предназначены для анализа чисел без знака; команды, осуществляющие переход по условию «больше — меньше», предназначены для анализа чисел со знаком.
Пример 1
cmp СХ,0 ;CX=0?
je equal ;Если да, перейти па метку equal
Пример 2
cmp AX,1000 ;Пусть AX=8000h=32768
;(=-32768)
ja above ;32768 > 1000. Переход будет
Пример 3
cmp AX,1000h ;Пусть AX=8000h=-32768
; (=32768)
jg greater ;-32768 < 1000h. Перехода не будет
Пример 4
int 21h ;Вызов системной функции
jc error ;Если CF=1 (ошибка), перейти
; на метку error
386+ Команды условных переходов имеют варианты 16- и 32-разрядной адресации (при тех же мнемонических обозначениях) и могут передавать управление в диапазоне -32768…+32767 байт для сегментов с атрибутом размера 16 и в диапазоне -231…+23|-1 байт для сегментов с атрибутом размера 32.
JMP Безусловный переход
Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.
Команда jmp имеет пять разновидностей:
— переход прямой короткий (в пределах -128… + 127 байтов);
— переход прямой ближний (в пределах текущего программного сегмента) ;
— переход прямой дальний (в другой программный сегмент);
— переход косвенный ближний;
— переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид перехода по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы:
short — прямой короткий переход;
near ptr — прямой ближний переход;
far ptr — прямой дальний переход;
word ptr — косвенный ближний переход;
dword ptr — косвенный дальний переход.
Примеры прямого короткого перехода
jmp short shpt ;Переход на метку shpt
;в пределах +127…-128 байтов
jmp shpt ;To же самое, если shpt
;находится выше по тексту программы
Примеры прямого ближнего перехода
jmp pt ;Переход на метку pt
;в пределах текущего сегмента
jmp near ptr pt ;To же самое
Примеры косвенных ближних переходов
Пример 1
mov BX,offset pt ;ВХ=адрес точки перехода
jmp BX ;Переход в точку pt
Пример 2
;В полях данных:
addr dw pt ;Ячейка с адресом точки перехода
;В программном сегменте:
jmp DS:addr ;Переход в точку pt
jmp word ptr addr ;To же самое
Пример 3
; В полях данных:
addr dw pt ;Ячейка с адресом точки перехода
;В программном сегменте:
mov DI,offset addr ;В1=адрес ячейки с адресом
;точки перехода
jmp [DI] ;Переход в точку pt
Пример 4
;В полях данных:
tbl dw ptl ;Ячейка с адресом 1
dw pt2 ;Ячейка с адресом 2
dw pt3 ;Ячейка с адресом 3
;В программном сегменте:
mov BX,offset tbl ;BX=aflpec таблицы адресов переходов
mov SI, 4 ;31=смещение к адресу pt3
call [BX][SI] ;Переход в точку pt3
Примеры прямых дальних переходов
jmp far ptr farpt ;Переход на метку farpt в
;другом программном сегменте
jmp farpt ;Переход на метку farpt в другом
;программном сегменте, если farpt
;объявлена дальней меткой
;директивой farpt label far
Примеры косвенных дальних переходов
Пример 1
; В полях данных:
addr dd pt ;Поле с двухсловным
;адресом точки перехода ;В программном сегменте:
jmp DS:addr ;Переход в точку pt
jmp dword ptr addr ;To же самое
Пример 2
; В полях данных:
addr dd pt ;Поле с двухсловным
;адресом точки перехода
;В программном сегменте:
mov DI,offset addr ;DI =адрес поля с адресом
;точки перехода jmp [DI] ;Переход в точку pt
386+ Допустимо использование дополнительных режимов адресации 32-разрядных процессоров. Для 32-разрядных приложений допустимо использование 32-битовых операндов. В защищенном режиме вместо сегментного адреса сегмента (при дальних переходах) выступает его селектор.
LAHF Загрузка флагов в регистр АН
Команда lahf копирует флаги SF, ZF, AF, PF и CF соответственно в разряды 7, 6, 4, 2 и 0 регистра АН. Значение битов 5, 3 и 1 регистра АН не определено. Команда не имеет параметров и не изменяет флаги процессора.
Команда lahf (совместно с командой sahf) дает возможность читать и изменять значения флагов процессора, в том числе флагов SF, ZF, AF и PF, которые нельзя изменить непосредственно. Однако следует иметь в виду, что команда lahf переносит в АН только младший байт регистра флагов. Поэтому нельзя изменить с ее помощью, например, состояние флага OF.
Пример 1
lahf ;Регистр АН отображает
;состояние регистра флагов
or AH,80h ;Установка бита 7 = SF
sahf ;Загрузка АН в регистр
;флагов, где теперь SF = 1
Пример 2
lahf ;Регистр АН отображает
;состояние регистра флагов
and AH,0BFh ;Сброс бита 6 = ZF
sahf ;Загрузка АН в регистр
;флагов, где теперь ZF = О
386Р+ LAR Загрузка прав доступа
Команда lar загружает в первый операнд (16- или 32-разрядный регистр) поле атрибутов сегмента из дескриптора сегмента, заданного селектором во втором операнде. В качестве операнда с селектором может использоваться 16- или 32-разрядный регистр или ячейка памяти. В операнд-приемник поступают два байта атрибутов селектора с замаскированным полем старших битов границы сегмента.
LDS Загрузка указателя с использованием регистра DS
Команда Ids считывает из памяти по указанному адресу двойное слово (32 бит), содержащее указатель (полный адрес некоторой ячейки), и загружает младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр, а старшую половину указателя (т.е. сегментный адрес) в регистр DS. Таким образом, команда
Ids reg, mem
эквивалентна следующей группе команд:
mov reg,word ptr mem
mov DS,word ptr mem+2
В качестве первого операнда команды Ids указывается регистр общего назначения; в качестве второго — ячейка памяти с двухсловным содержимым. Указатель, содержащийся в этой ячейке, может быть адресом как процедуры, так и поля данных. Команда не воздействует на флаги процессора.
Пример 1
; В полях данных:
addr dd myproc ;Двухсловный адрес процедуры
;myproc
;В программном сегменте:
Ids SI,addr ;DS:SI -> myproc
Пример 2
; В полях данных:
mem dw 25 ;Ячейка памяти с
; произвольным содержимым
addr dd myproc ;Двухсловный адрес этой
;ячейки
;В программном сегменте:
mov BX,offset addr ;ВХ=адрес ячейки addr
Ids DX, [BX] ;DХ=смещение ячейки mem,
;DS=сегментный адрес ячейки
;mem
Пример 3
; В полях данных:
dptr dd procl ;Полный адрес процедуры
; р г о с 1
dd proc2 ;Полный адрес процедуры
;ргос2
dd ргосЗ ;Полный адрес процедуры
; р г о с 3
;В программном сегменте:
mov SI, 8 ; Смещение к адресу ргосЗ
Ids DI,dptr[SI] ;DS:DI ® ргосЗ
386+ Допустимо использование 32-разрядного регистра-приемника и 32-битового смещения в памяти, а также дополнительных режимов адресации 32-разрядных процессоров. В защищенном режиме вместо сегментного адреса сегмента выступает его селектор.
LEA Загрузка исполнительного адреса
Команда lea загружает в регистр, указанный в команде в качестве первого операнда, относительный адрес второго операнда (не значение операнда!). В качестве первого операнда следует указывать регистр общего назначения (не сегментный), в качестве второго — ячейку памяти. Команда
lea reg,mem
эквивалентна команде
mov reg,offset mem
но у первой команды больше возможностей описания адреса интересующей нас ячейки. Команда не воздействует на флаги процессора.
Пример 1
; В полях данных:
message db ; ‘Идут измерения’
;В программном сегменте:
lea SI,message ;DS:SI -> message
Пример 2
; В полях данных:
nmb db ‘0123456789’
;В программном сегменте:
mov SI,7 ;Смещение символа ‘7’
lea DX,nmb[SI] ;ВХ=адрес символа ‘7’
Пример 3
; В полях данных:
nmb db ‘0123456789’
;В программном сегменте:
mov BX, off set msg
mov SI, 9 ;Смещение символа ‘9’
lea SI, [BX] [SI] ;31=адрес символа ‘9’
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
386+ LEAVE Выход из процедуры высокого уровня
Команда leave выполняет действия, противоположные действиям последней команды enter. Она логически уничтожает созданный командой enter стековый кадр со всеми содержащимися в нем локальными переменными и подготавливает стек к выполнению команды irct, завершающей переход в вызывающую процедуру. Команда leave не имеет параметров. Более подробное описание и пример см. в описании команды enter.
LES Загрузка указателя с использованием регистра ES
Команда les считывает из памяти по указанному адресу двойное слово (32 бит), содержащее указатель (полный адрес некоторой ячейки), и загружает младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр, а старшую половину указателя (т.е. сегментный адрес) в регистр ES. Таким образом, команда
les reg,mem
эквивалентна следующей группе команд:
mov reg,word ptr mem mov ES,word ptr mem+2
В качестве первого операнда команды les указывается регистр общего назначения; в качестве второго — ячейка памяти с двухсловным содержимым. Указатель, содержащийся в этой ячейке, может быть адресом как процедуры, так и поля данных. Команда не воздействует на флаги процессора.
Пример 1
;В полях данных:
addr dd myproc ;Двухсловный адрес процедуры
;myproc
;В программном сегменте:
les SI,addr ;ES:SI ® myproc
Пример 2
;В полях данных:
mem dw 25 ;Ячейка памяти с
;произвольным содержимым
addr dd myproc ;Двухсловный адрес этой ячейки
;В программном сегменте:
mov BX,offset addr ;ВХ=адрес ячейки addr
…
les DX, [BX] ; DХ=смещение ячейки mem,
;ЕS=сегментный адрес ячейки mem
Пример 3
;В полях данных:
dptr dd procl ;Полный адрес процедуры prod
dd proc2 ;Полный адрес процедуры ргос2
dd ргосЗ ;Полный адрес процедуры ргосЗ
;В программном сегменте:
mov SI, 8 ;Смещение к адресу ргосЗ
les DI,dptr[SI] ;ES:DI -> ргосЗ
386+ Допустимо использование 32-разрядного регистра-приемника и 32-битового смещения в памяти, а также дополнительных режимов адресации 32-разрядных процессоров. В защищенном режиме вместо сегментного адреса сегмента выступает его селектор.
386+ LFS Загрузка указателя с использованием регистра FS
Команды считывают из памяти полный указатель, состоящий из селектора и 16-битового или 32-битового смещения, и загружают младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр общего назначения, а старшую половину указателя (т.е. селектор) в сегментный регистр, указанный в мнемонике команды.
В качестве первого операнда всех перечисленных команд указывается 16- или 32-разрядный регистр общего назначения; в качестве второго — ячейка памяти с 32- или 48-битовым содержимым. Команда не воздействует на флаги процессора.
Примеры см. в описании команд Ids и les.
386Р+ LGDT Загрузка регистра таблицы глобальных дескрипторов
Команда Igdt загружает регистр таблицы глобальных дескрипторов (GDTR) из 48-битового псевдодескриптора, содержащего 32-битовый базовый адрес и 16-битовую границу таблицы глобальных дескрипторов, находящейся в памяти. В качестве операнда команды Igdt выступает относительный адрес псевдодескриптора.
386Р+ LIDT Загрузка регистра таблицы дескрипторов прерываний
Команда lidt загружает регистр таблицы дескрипторов прерываний (IDTR) из 48-битового псевдодескриптора, содержащего 32-битовый базовый адрес и 16-битовую границу таблицы дескрипторов прерываний, находящейся в памяти. В качестве операнда команды lidt выступает относительный адрес псевдодескриптора.
386Р+ LLDT Загрузка регистра таблицы локальных дескрипторов
Команда lldt загружает регистр таблицы локальных дескрипторов (LDTR) селектором, определяющим таблицу локальных дескрипторов (LDT). Селектор LDT должен входить в таблицу глобальных дескрипторов. В качестве операнда команды lldt, содержащего селектор LDT, можно использовать 16- или 32-разрядный регистр общего назначения или 16-или 32-битовое поле памяти.
386Р+ LMSW Загрузка слова состояния машины
Команда Imsw загружает в регистр слова состояния машины (так называется младшая половина управляющего регистра процессора CRO) слово состояния машины, взятое из указанного в команде операнда. В качестве операнда можно использовать 16- или 32-разрядный регистр общего назначения или 16- или 32-битовое поле памяти.
Команду Imsw можно использовать для перевода процессора из реального в защищенный режим или наоборот. В первом случае после чтения слова состояния командой smsw надо установить в нем бит 0 (бит РЕ) и загрузить назад в CRO командой Imsw. Во втором случае после после чтения слова состояния командой smsw надо сбросить в нем бит 0 и загрузить назад в CRO командой Imsw.
LOCK Запирание шины
Префикс lock, помещенный перед командой, устанавливает сигнал на линии LOCK системной шины и запрещает доступ к шине другим процессорам на время выполнения данной команды. Этот префикс предназначен для использования в многопроцессорных многозадачных системах для обеспечения исключительного доступа к памяти данного процесса (и данного процессора) на время проверки или модификации некоторой ячейки памяти. Типичный пример операций такого рода — работа с семафорами.
Если два (или более) процесса, идущие на разных процессорах, используют какой-либо общий ресурс, например, файл или лазерный диск, то необходимо обеспечить механизм, запрещающий одновременное обращение процессов к общему ресурсу. Эта задача решается с помощью семафора — ячейки памяти (байта или даже бита), состояние которого отражает доступность или, наоборот, занятость ресурса.
Если процессору понадобился общий ресурс, он читает состояние семафора и, если ресурс занят, продолжает опрашивать семафор до тех пор, пока другой процессор, использующий в настоящий момент общий ресурс, не освободит его. Обнаружив, что ресурс свободен, первый процессор устанавливает семафор в состояние «занят» и использует ресурс. Закончив работу с ресурсом, процессор сбрасывает его семафор и дает возможность другому процессу обратиться к тому же ресурсу.
Описанный алгоритм будет работать только в том случае, если операция чтения-модификации-записи семафора будет выполняться в непрерываемом режиме. В противном случае оба процесса могут, одновременно обратившись к семафору, увидеть, что ресурс свободен, и начать его совместное использование. Избежать такой ситуации и позволяет префикс lock в сочетании с командами типа btr или bts, выполняющими комплексные операции проверки и сброса или проверки и установки бита.
Будем считать, что семафор расположен в бите 0 байта по адресу sem, причем сброшенное состояние бита свидетельствует о занятости ресурса, а установленное состояние о том, что ресурс свободен. Тогда типичная процедура ожидания освобождения ресурса выглядит следующим образом:
mov SI,offset sem ;Адрес байта с семафором
getsem:
lock btr byte ptr [SI],1 ;Проверка и сброс бита 0
jnc getsem
Проверка состояния семафора и его модификация (запись в бит семафора 0, т.е. признака «занят») осуществляется в одной команде btr. На время выполнения этой команды шина многопроцессорной системы блокируется префиксом lock, и другой процессор обратиться к тому же семафору не может. Блокировка шины снимается уже после того, как семафор будет переведен в состояние занятости.
Если при обращении к байту sem оказывается, что в битс семафора записан 0, т.е. ресурс занят другим процессом, команда btr сбрасывает флаг CF (путем переноса в него содержимого анализируемого бита), что приводит к многократному повторению процедуры getsem, т.е. к циклу ожидания освобождения ресурса.
Типичная процедура освобождения занятого данным процессом ресурса выглядит следующим образом:
freesem:
lock bts byte ptr [SI],1 ;Проверка и установка бита 0
Собственно говоря, никакая проверка здесь не выполняется, однако процесс будет освобождать ресурс лишь если он этот ресурс использует, и проверять состояние флага в этой операции нет необходимости. Однако и здесь необходимо запирание шины на время записи в бит семафора 1, чтобы исключить одновременное обращение двух процессов к одной ячейке памяти.
386+ Префикс lock может быть использован только со следующими командами (и лишь при условии, что при их выполнении происходит обращение к памяти): adc, add, and, bt, bts, btr, btc, or, sbb, sub, xor, xchg, dec, inc, neg, not.
LODS Загрузка операнда из строки
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они загружают в регистр AL (в случае операций над байтами) или АХ (в случае операций над словами) содержимое ячейки памяти по адресу, находящемуся в паре регистров DS:SI. Команда lodsb загружает 1 байт, команда lodsw — 1 слово, а команда lods может быть использована для загрузки как байтов, так и слов. В последнем случае размер загружаемого данного определяется описанием строки (с помощью директив db или dw). После операции загрузки регистр SI получает положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1 или 2, в зависимости от размера загружаемого элемента. Команда не имеет параметров и не воздействует на флаги процессора.
Вариант команды lods имеет формат
lods строка
(что не избавляет от необходимости инициализировать регистры DS:SI адресом строки). В этом формате возможна замена сегмента строки строка:
lods ES:строка
Пример 1
;В полях данных сегмента данных, адресуемого через DS:
str db ‘qwertyuiop’
; В программном сегменте:
сld ;Двигаемся по строке вперед
mov SI, off set str ;Адрес строки
add SI,BX ;Добавим смещение (пусть ВХ=4)
lodsb ;AL=’t’, SI -> ‘у’
Пример 2
;В полях данных сегмента данных, адресуемого через ES:
str db ‘qwertyuiop’
;В программном сегменте:
сld ;Двигаемся по строке вперед
mov SI,offset str ;Адрес строки
lodsbES:str ;AL=’q’, ES:SI -> ‘w’
386+ LODSD Загрузка двойного слова из строки
Команда аналогична командам МП 86 lodb и lodsw, но позволяет загрузить из строки, адресуемой через регистры DS:ESI (DS:SI для 16-разрядных приложений), двойное слово в регистр ЕАХ.
Пример
; В полях данных
dat dd 12789,200000,550000,8000000
;В программном сегменте
mov SI,offset dat
add SI, 4*3 ;DS:SI -> 4-й элемент массива чисел
lodsd ;EAX=8000000
LOOP Циклическое выполнение, пока содержимое СХ не равно нулю
Команда loop выполняет декремент содержимого регистра СХ, и если оно не равно 0, осуществляет переход на указанную метку вперед или назад в том же программном сегменте в диапазоне -128… + 127 байт. Обычно метка помещается перед первым предложением тела цикла, а команда loop является последней командой цикла. Содержимое регистра СХ рассматривается как целое число без знака, поэтому максимальное число повторений группы включенных в цикл команд составляет 65536 (если перед входом в цикл СХ=0). Команда не воздействует на флаги процессора.
Пример 1
;В полях данных:
array dw 4096 dup (?) ;Массив из 4096 слов
;В программном сегменте:
lea BX,array ;ВХ -> array
xor SI,SI ;SI=0
mov CX,4096 ;Счетчик повторений
mov AX,1 ;Число-заполнитель
array: mov [BX] [SI],AX ;Очистка элемента массива
inc SI ;Сдвиг к следующему
inc SI ;слову массива
loop array ;Повторить СХ раз
Пример 2
mov CX,20
delay :loop delay ;Небольшая задержка
386+ При использовании в качестве счетчика расширенного регистра ЕСХ максимальное число шагов в цикле увеличивается до 232. Для того чтобы в 16-разрядном приложении процессор при выполнении команды loop использовал не 16-разрядный регистр СХ, а 32-разрядный регистр ЕСХ, перед командой loop необходимо указать префикс замены размера адреса 67h.
Пример
mov ЕСХ,О
zzzz: db 67h ;Префикс замены размера адреса
loop zzzz ;Цикл из 232: шагов, реализующий
;программную задержку порядка минут
LOOPE/LOOPZ Циклическое выполнение,пока равно/циклическое выполнение, пока нуль
Оба обозначения представляют собой синонимы и относятся к одной команде. Команда выполняет декремент содержимого регистра СХ, и если оно не равно 0, и флаг ZF установлен, осуществляет переход на указанную метку вперед или назад в том же программном сегменте в диапазоне -128…+127 байтов. Содержимое регистра СХ рассматривается как целое число без знака, поэтому максимальное число повторений группы включенных в цикл команд составляет 65536. Команда не воздействует на флаги процессора.
Пример
;В полях данных, адресуемых через DS:
command db 80 dup (‘ ‘)
;В программном сегменте:
. . . ;Копирование в поле command строки,
;содержимое которой следует анализировать
lea SI, command ;Настроим DS:SI
сld ;Обработка вперед
mov CX,80 ;Обрабатывать не более 80
;байтов
pass: lodsb ;Загрузим в AL очередной
;символ
сmр АL, ‘ ‘ ;Пропустим все пробелы в
loopepass ;начале строки
dec SI ;Сдвиг на 1 символ назад
;DS:SI -> первый символ, отличный от пробела
386+ При использовании в качестве счетчика расширенного регистра ЕСХ максимальное число шагов в цикле увеличивается до 232. Для того, чтобы в 16-разрядном приложении процессор при выполнении команд loope/loopz использовал не 16-разрядный регистр СХ, а 32-разрядный регистр ЕСХ, перед командами loope/loopz необходимо указать префикс замены размера адреса 67h.
Пример
mov ЕСХ, 1000000 ;Предельное число шагов
хххх: … ;Тело цикла
db 67h
loopexxxx
LOOPNE/LOOPNZ Циклическое выполнение, пока не равно/циклическое выполнение, пока не нуль
Оба обозначения представляют собой синонимы и относятся к одной команде. Команда выполняет декремент содержимого регистра СХ, и если оно не равно 0, и флаг ZF сброшен, осуществляет переход на указанную метку вперед или назад в том же программном сегменте в диапазоне -128… + 127 байтов. Содержимое регистра СХ рассматривается как целое число без знака, поэтому максимальное число повторений группы включенных в цикл команд составляет 65536. Команда не воздействует на флаги процессора.
Пример
;В полях данных:
command db 80 dup (0)
;В программном сегменте:
. . . ;Копирование в поле command строки,
; содержимое которой следует анализировать
lea SI,command ;Настроим DS:SI
cld ;Обработка вперед
mov CX,80 ;Обрабатывать не более 80
;байтов
slash: lodsb ;Загрузим в AL очередной символ
cmp AL, ‘ / ‘ ;Ищем знак ‘ / ‘
loopne slash ;во всей строке
;DS:SI -> первый символ за знаком ‘/’
386+ При использовании в качестве счетчика расширенного регистра ЕСХ максимальное число шагов в цикле увеличивается до 232. Для того чтобы в 16-разрядном приложении процессор при выполнении команд loopne/loopnz использовал не 16-разрядный регистр СХ, а 32-разрядный регистр ЕСХ, перед командами loopne/loopnz необходимо указать префикс замены размера адреса 67h.
Пример
mov ЕСХ,1000000 ;Предельное число шагов
хххх: . . . ;Тело цикла
db 67h
loopne xxxx
386Р+ LSL Загрузка границы сегмента
Команда Isl загружает в первый операнд границу сегмента из дескриптора сегмента, заданного селектором во втором операнде.
В качестве первого операнда команды Isl можно использовать 16- или 32-разрядный регистр общего назначения; в качестве второго — 16- или 32-разрядный регистр общего назначения или 16- или 32-битовое поле памяти.
386Р+ LTR Загрузка регистра задачи TR
Команда Itr загружает регистр задачи TR селектором сегмента состояния задачи TSS из второго операнда, в качестве которого можно использовать 16- или 32-разрядный регистр общего назначения или 16- или 32-битовое поле памяти. Команда используется в защищенном режиме, если программный комплекс выполнен в виде нескольких самостоятельных задач, и переключения между ними осуществляются с использованием включенных в процессор аппаратных средств поддержки многозадачности.
MOV Пересылка данных
Команда mov замещает первый операнд (приемник) вторым (источником). При этом исходное значение первого операнда теряется. Второй операнд не изменяется. В зависимости от описания операндов, пересылается слово или байт. Если операнды описаны по-разному или режим адресации не позволяет однозначно определить размер операнда, для уточнения размера передаваемых данных в команду следует включить один из атрибутных операторов byte ptr или word ptr. Команда не воздействует на флаги процессора. В зависимости от используемых режимов адресации, команда mov может осуществлять пересылки следующих видов:
— из регистра общего назначения в регистр общего назначения;
— из регистра общего назначения в ячейку памяти;
— из регистра общего назначения в сегментные регистры DS, ES и SS;
— из ячейки памяти в регистр общего назначения;
— из ячейки памяти в сегментный регистр;
— из сегментного регистра в регистр общего назначения;
— из сегментного регистра в ячейку памяти;
— непосредственный операнд в регистр общего назначения;
— непосредственный операнд в ячейку памяти.
Запрещены пересылки из ячейки памяти в ячейку памяти (для этого предусмотрена команда movs), а также загрузка сегментного регистра непосредственным значением, которое, таким образом, приходится загружать через регистр общего назначения:
mov AX,seg mem ;Сегментный адрес ячейки mem
mov DS,AX ;Загрузка его в регистр DS
Нельзя также непосредственно переслать содержимое одного сегментного регистра в другой. Такого рода операции удобно выполнять с использованием стека:
push DS
pop ES ; DS копируется в ES
Примеры
;В полях данных:
memb db 5,6
memd dd 0 ;Двухсловная ячейка
;В программном сегменте:
mov DX,AX ;Из регистра в регистр
mov AL,memb ;Из памяти в регистр
mov AX,0B800h ;Непосредственное значение в
;регистр
mov ES,AX ;Из регистра в сегментный
;регистр
mov word ptr memd+2,ES ;Из сегментного
;регистра в память
mov word ptr memd, 2000;Непосредственное
;значение в память
mov BX,word ptr memb ;Слово из памяти в
;регистр (число 0605)
mov DI,word ptr memd ;Слово из памяти в
;регистр
mov ES,word ptr memd+2;Слово из памяти в
;сегментный регистр
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример 1
mov EAX,ESI
Пример 2
; В полях данных
mem dd 0
;В программном сегменте
mov mem,EBP
386Р+ MOV Пересылка в\из специальных регистров
Этот вариант команды mov (с той же мнемоникой, но другими кодами операций) используется в защищенном режиме и предназначен для обмена данными со специальными регистрами процессора: управляющими CRO…CR3, тестирования TR6 и TR7, а также регистрами отладки DRO…DR7. Один из операндов команды mov должен быть 32-разрядным регистром общего назначения, другим — один из специальных регистров процессора.
MOVS Пересылка данных из строки в строку
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они пересылают по одному элементу строки, который может быть байтом или словом. Первый операнд (приемник) адресуется через ES:DI, второй (источник) — через DS:SI. Операцию пересылки можно условно изобразить следующим образом:
(DS:SI) -> (ES:DI)
После каждой операции пересылки регистры SI и DI получают положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1 или 2 в зависимости от размера пересылаемых элементов. Вариант команды movs имеет формат:
movs строка_1, строка_2
В этом случае байты или слова из строки строка_2 пересылаются на место строки строка_]. Размер пересылаемых элементов определяется описанием строк (с помощью директив db или dw). Это не избавляет от необходимости инициализировать регистры ES:DI и DS:SI адресами строк строка _1 и строка_2. В этом формате возможна замена сегмента второй строки (источника):
movs строка_1, ES:строка_2
Рассматриваемые команды могут предваряться префиксом повторения rep (повторять СХ раз). После выполнения рассматриваемых команд регистры SI и DI указывают на ячейки памяти, находящиеся за теми (если DF=0) или перед теми (если DF=1) элементами строк, на которых закончились операции пересылки. Если флаг DF сброшен, то пары регистров DS:SI и ES:DI следует инициализировать начальными адресами строк-операндов; строка-источник будет пересылаться от се начала, в порядке возрастания номеров ее байтов. Если флаг DF установлен, то пары регистров DS:SI и ES:DI следует инициализировать конечными адресами строк-операндов; строка-источник будет пересылаться от ее конца, в порядке уменьшения номеров ее байтов. Команды не воздействует на флаги процессора.
Пример 1
;В полях данных основного сегмента данных,
;адресуемого через DS:
txt db ‘Урок 1’ ;Пересылаемая строка
txt_len equ S-txt ;Ee длина
;В ‘полях данных дополнительного сегмента данных,
;адресуемого через ES :
string db 80 dup (‘ ‘)
;В программном сегменте:
lea SI,txt ;DS:SI -> txt
lea DI,string+10.;ES:DI -> string+10
сld ;Движение по строке вперед
mov CX,txt_len ;Столько байтов переслать
rep movsb ;Пересылка
Пример 2
;В полях данных сегмента данных, адресуемого через DS:
txt db ‘А’,84h, ‘В’,84h, ‘A’,84h, ‘P’,
db 84h,’И’,84h,’Я’,84h,’!’,84h
txt_len=$-txt ;B программном сегменте:
mov AX,0B800h ;Сегментный адрес видеобуфера
mov ES,AX ;Инициализируем ES
;Выведем на экран текст
mov DI,1672 ;Смещение к середине экрана
lea SI,txt ;DS:SI ® txt
сld ;Движение по строке вперед
mov CX,txt_len/2 ;Столько слов переслать
rep movsw ;Пересылка в середину экрана
;красной мерцающей (атрибут
;84h) надписи ‘АВАРИЯ!’
Пример 3
;В полях данных сегмента данных, адресуемого через DS:
datal dw 10000 dup(‘) ;Массив произвольных данных
data2 dw 5000 dup(‘) ;Массив-приемник
;В программном сегменте
push DS ;Настроим
pop ES ;ES на тот же сегмент данных
mov SI,offset datal;SI -> datal
add SI,5000 ;Сместим SI к середине
;массива
mov DI,offset data2;DI -> data2
mov CX,2500 ;Размер половины массива (в
;словах)
сld ;Движение вперед
rep movsw ;Перешлем вторую половину
;массива datal на место data2
Пример 4
;В полях данных сегмента, адресуемого через DS
file db ‘MYFILE.01.DAT1,0 ;Строка-источник
fname db 128 dup(?) ;Строка-приемник
;В программном сегменте
push DS
pop ES ;Теперь ES=DS
mov SI,offset file;DS:SI -> strl
mov SI,128 ;Максимальная длина имени
;файла
сld ;Движение по строке вперед
null: lodsb ;Загрузим в AL очередной
; символ
cmp AL, 0 ;Ищем 0 в конце имени файла
loopne null
;DS:SI ® Первый символ за концом имени файла (за
;завершающим нулем)
dec SI ;SI -> байт с 0 std ;Движение по строке назад
mov ВХ,128 ;Из начального значения СХ
sub BX,CX ;вычтем то, что в СХ осталось
mov СХ,ВХ ;СХ=число символов в имени (с 0)
dec ВХ ;Смещение к 0 от начала имени файла
lea DI,fname[ВХ] ;Смещение завершающего 0
rep movsb ;Перешлем все имя (от конца к началу)
386+ MOVSD Пересылка двойного слова из строки в строку
Команда аналогична командам МП 86 movsb и movsw, но позволяет скопировать двойное слово из строки, адресуемой через регистры DS:ESI, в строку, адресуемую через регистры ES:EDI.
Пример 1
;В полях данных сегмента, адресуемого через DS
strl db ‘01234567890ABCDEF’ ;Строка-источник
str2 db 16 dup(?) ;Строка-приемник
;B программном сегменте
push DS
pop ES ;Теперь ES=DS
mov SI,offset strl ;DS:SI ®strl
mov DI,offset str2 ;ES:DI -> str2
сld ;Движение по строке вперед
mov CX,4 ;Коэффициент повторения
rep movsd ;Копирование по 4*4 байт
386+ MOVSX Пересылка с расширением знака
Команда пересылает байт в слово или двойное слово, а также слово в двойное слово с расширением знака. В качестве первого операнда (приемника) может использоваться 16- или 32-разрядный регистр общего назначения, в качестве второго — 8- или 16-разрядный регистр общего назначения или ячейка памяти такого же размера. Недопустима пересылка из памяти в память, в или из сегментного регистра, а также непосредственного значения. Фактически команда movsx увеличивает размер как положительного, так и отрицательного числа, ни изменяя ни его значения, ни знака.
Пример 1
mov CL,-5 ;CL=FBh
movsxAX,CL ;AX=FFFBh
Пример 2
mov CL,+5 ;CL=05h
movsxAX,CL ;AX=0005h
Пример 3
mov BL,-128 ;BL=80h
movsxECX,BL ;ECX=FFFFFF80h
Пример 4
; В полях данных
mem dw -3 ;mem=FFFDh
;В программном сегменте
movsxEB-X,mem ; EBX=FFFFFFFDh
386+ MOVZX Пересылка с расширением нуля
Команда пересылает байт в слово или двойное слово, а также слово в двойное слово с заполнением старших разрядов нулями. В качестве первого операнда (приемника) может использоваться 16- или 32-разрядный регистр общего назначения, в качестве второго — 8- или 16-разрядный регистр общего назначения или ячейка памяти такого же размера. Недопустима пересылка из памяти в память, в или из сегментного регистра, а также непосредственного значения. Фактически команда movzx увеличивает размер числа, считая его числом без знака.
Пример 1
mov CL,5 ;CL=05h
movsxAX,CL ;AX=0005h
Пример 2
mov CL,-5 ;CL=FBh
movsxAX,CL ;AX=00FBh
Пример 3
mov BL,80h ;BL=80h
movsxECX,BL ;ECX=00000080h
Пример 4
;B полях данных
mem dw 0FFFFh ;mem=FFFFh
;B программном сегменте
movsxEBX,mem ;EBX=0000FFFFh
MUL Умножение целых чисел без знака
Команда inul выполняет умножение целого числа без знака, находящегося в регистре AL (в случае умножения на байт) или АХ (в случае умножения на слово), на операнд-источник (целое число без знака). Размер произведения в два раза больше размера сомножителей.
Для однобайтовых операций один из сомножителей помещается в регистр AL; после выполнения операции произведение записывается в регистр АХ.
Для двухбайтовых операций один из сомножителей помещается в регистр АХ; после выполнения операции произведение записывается в регистры DX:AX (в DX — старшая часть, в АХ — младшая). Предыдущее содержимое регистра DX затирается.
Если содержимое регистра АН после однобайтового умножения или содержимое регистра DX после двухбайтового умножения не равны 0, флаги CF и OF устанавливаются в 1. В противном случае оба флага сбрасываются в 0.
В качестве операнда-сомножителя команды mul можно указывать регистр (кроме сегментного) или ячейку памяти; не допускается умножение на непосредственное значение. Команда воздействует на флаги OF и CF.
Пример 1
mov AL,5 ;Первый сомножитель
mov BL,3 ;Второй сомножитель
mul BL ;AX=000Fh, произведение
Пример 2
mov AX,256 ;Первый сомножитель
mov BX,256 ;Второй сомножитель
mul BX ;DX=0001h, AX=0000h
;(DX:AX=65536, произведение)
Пример 3
;В полях данных
coef db 100 ;Первый сомножитель
datal db 126 ;Второй сомножитель
mov AL,datal ;AL=7Eh=126
mul coef ;AX=3138h=12600,произведение
Пример 4
;B полях данных
coef dw 5000 ;Первый сомножитель
datal dw 1200 ;Второй сомножитель
mov AX,datal ;AX=4BOh=1200
mul coef ;DX=005Bh, AX=8D80h
;Произведение=ВХ:AX=
;5B8D80h=6000000
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. При этом, если указанный операнд представляет собой 32-байтовую величину, то результат размещается в регистрах EDX:EAX.
Пример 1
mov EAX,200h ;Первый сомножитель
mov ESI,l000000lh ;Второй сомножитель
mul ESI ;Произведение в EDX:EAX
;EDX=00000020h,EAX=00000200h
Пример 2
; В полях данных
nmbs db 15,22,36,78,84,98,100
;В программном сегменте
mov EDX,offset nmbs ;Относительный адрес
movzx EDX,DX ;массива
mov ECX,5 ;Смещение в массиве
mov AL,10 ;Множитель
mul byte ptr [EDX] [ЕСХ] ;Умножаем элемент
;массива с индексом 5 (98)
;на AL (10) Результат в
;АХ=980
NEG Изменение знака, дополнение до 2
Команда neg выполняет вычитание целочисленного операнда со знаком из нуля, превращая положительное число в отрицательное и наоборот. Исходный операнд затирается. В качестве операнда можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
mov АХ,О О 01
neg AX ;AX=FFFFh=-l
Пример 2
mov BX,-2 ;BX=FFFEh=-2
neg BX ;BX=0002h
Пример 3
;В полях данных
nmb dw 800lh ;Если число со знаком,
;то -32767
;В программном сегменте
neg nmb ;nmb=7FFFh=+32767
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov ECX, 5
neg ECX ;ECX=FFFFFFFBh=-5
NOP Холостая команда
По команде пор процессор не выполняет никаких действий, кроме увеличения на 1 содержимого указателя команд IP (поскольку команда пор занимает 1 байт). Команда иногда используется в отладочных целях, чтобы «забить» какие-то ненужные команды, не изменяя длину загрузочного модуля или, наоборот, оставить место в загрузочном модуле для последующей вставки команд. В ряде случаев команды пор включаются в текст объектного модуля транслятором. Команда не имеет ни параметров, ни операндов и не воздействует на флаги процессора.
NOT Инверсия, дополнение до 1, логическое отрицание
Команда not выполняет инверсию битов указанного операнда, заменяя 0 на 1 и наоборот. В качестве операнда можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда не воздействует на флаги процессора.
Правила побитовой инверсии:
Операнд-бит 0 1
Бит результата 1 0
Пример 1
mov AX,0FFFFh
not AX ;AX=0000h
Пример 2
mov SI,5551h
not SI ;SI=AAAEh
386+ Допустимо использование 32-битовых операндов и дополнитель ных режимов адресации 32-разрядных процессоров.
Пример
mov EAX,0C00SFF00h
not EAX ;EAX=3FFC00FFh
OR Логическое ВКЛЮЧАЮЩЕЕ ИЛИ
Команда or выполняет операцию логического (побитового) сложения двух операндов. Результат замещает первый операнд (приемник); второй операнд (источник) не изменяется. В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды команды or могут быть байтами или словами. Команда воздействует на флаги OF, SF, ZF, PF и CF, при этом флаги CF и OF всегда сбрасываются в 0.
Правила побитового сложения:
Первый операнд-бит 0101
Второй операнд-бит 0011
Бит результата 0111
Пример 1
mov AX,000Fh
mov BX,00F0h
or AX,BX ;AX=00FFh, BX=00F0h
Пример 2
mov AX,000Fh
mov BX,00F7h
or AX,BX ;AX=00FFh, BX=00F7h
Пример 3
mov AX,000Fh
or AX,8001h ;AX=800Fh
Пример 4
; В полях данных
mask db 80h
;B программном сегменте
mov CH,17h
or CH,mask ;CH=97h
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
;В полях данных
mem dd 80000000h
; В программном сегменте
or mem,0C0h ;mem=800000C0h
OUT Вывод в порт
Команда out выводит в порт, указываемый первым операндом, байт или слово соответственно из регистра AL или АХ. Адрес порта помещается в регистр DX. Если адрес порта не превышает 255, он может быть указан непосредственным значением. Указание регистра-источника (AL или АХ) обязательно, хотя с другими регистрами команда out не работает, и их указывать нельзя. Команда не воздействует на флаги процессора.
Пример 1
mov AL,20h ;Команда конца прерывания (EOI)
out 20h,AL ;Вывод команды EOI в порт
;20h контроллера прерываний
Пример 2
mov DX,3CEh ; Адрес порта
mov AL,5 ;Данное
out DX,AL ;Вывод байта из AL в порт 3CEh
386+ Допустимо использование в качестве операнда-источника расширенного регистра ЕАХ (если адресуемое устройство позволяет записать в его порт двойное слово).
Пример
mov ЕАХ,1А008РРЗh;Пересылаемое данное
mov DX,345h ;Адрес порта
out DX,EAX ;Вывод в порт двойного слова
386+ OUTS Вывод строки в порт
Команды предназначены для вывода данных в порт непосредственно из памяти. Адрес порта указывается, как и для команды out, в регистре DX, при этом задание адреса порта непосредственным значением не допускается. Данные извлекаются из памяти по адресу, находящемуся в паре регистров DS:ESI. Замена сегмента не допускается. Команда outsb передает в порт 1 байт, команда outsw — 1 слово, команда outsd — 1 двойное слово, а команда outs может быть использована для передачи байтов, слов и двойных слов. В последнем случае размер загружаемого данного определяется описанием строки (с помощью директив db, dw или dd). После передачи данных регистр ESI получает положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1, 2 или 4 в зависимости от размера передаваемых данных.
Вариант команды outs имеет формат
outs DX, строка
(что не избавляет от необходимости инициализировать регистры DS:ESI адресом строки).
Если устройство, адресуемое через порт, может принимать последовательность данных, то команды outs можно предварить префиксом повторения rep. В этом случае в порт пересылается СХ элементов данных заданного размера.
Команды outs не воздействуют на флаги процессора.
Пример 1
; В полях данных
mem dw 0FFh
;В программном сегменте
mov SI, offset mem;ES:DI ® mem
mov DX,303h ;Адрес порта
outsb ;Вывод в порт 8-битового
;данного
Пример 2
; В полях данных
string dw 0FFh,1,5,0Bh, 0
; В программном сегменте
mov SI, off set mem;ES:DI -> mem
mov DX,340h Адрес порта
mov CX, 5 ;Число данных
eld ;Движение по данным вперед
rep outsb ;Последовательный вывод в
;порт пяти 8-битовых данных
POP Извлечение слова из стека
Команда pop выталкивает 16-битовое данное из стека, т.е. пересылает слово из вершины стека (на которую указывает регистр SP) по адресу операнда-приемника. После этого содержимое SP увеличивается на 2, и SP указывает на предыдущее слово стека, которое теперь является его новой вершиной. Выталкивать из стека можно только целые слова (не байты). Программа должна строго следить за тем, чтобы каждой команде проталкивания в стек push отвечала обратная команда выталкивания из стека pop. Если стек используется для временного хранения некоторых данных, то извлекать эти данные из стека следует в порядке, обратном их сохранению.
В качестве операнда-приемника можно использовать любой 16-разрядный регистр (кроме CS) или ячейку памяти. Команда не воздействует на флаги процессора.
Пара команд push — pop часто используется для пересылки данного из регистра в регистр (особенно, в сегментный) через стек.
Пример 1
push AX ;Временное сохранение
push BX ;в стеке
push DS ;трех операндов
pop DS ;Восстановление из стека
pop BX ;трех операндов
pop AX ; в обратном порядке
Пример 2
push CS ;Пересылка CS через стек pop DS ;Теперь DS=CS
Пример 3
;В полях данных
mem dw 0
; В программном сегменте
pop mem ;Восстановление из стека в память
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
pop EAX ;Извлечение из стека двойного слова
386+ РОРА Восстановление из стека всех регистров
Команда рора восстанавливает из стека содержимое всех регистров, предварительно сохраненных в стеке командой pusha. Заполнение из стека регистров осуществляется в следующем порядке: DI, SI, BP, SP, ВХ, DX, СХ, АХ. Исходное содержимое указателя стека SP, сохраненное в стеке командой pusha, командой рора из стека извлекается, но отбрасывается. Команда не имеет параметров.
Пример
рора
386+ POPAD Восстановление из стека всех регистров в 32-разрядном режиме
Команда popad восстанавливает из стека содержимое всех расширенных регистров, предварительно сохраненных в стеке командой pushad. Заполнение из стека регистров осуществляется в следующем порядке: EDI, ESI, EBP, ESP, ЕВХ, EDX, ЕСХ, ЕАХ. Исходное содержимое указателя стека ESP, сохраненное в стеке командой pusha, командой рора из стека извлекается, но отбрасывается. Команда не имеет параметров.
Пример
popad
POPF Восстановление из стека регистра флагов
Команда popf пересылает верхнее слово стека (на которое указывает регистр SP) в регистр флагов FLAGS. После этого содержимое SP увеличивается на 2, и SP указывает на предыдущее слово стека, которое теперь является его новой вершиной. Команда popf не имеет параметров; она воздействует на все флаги процессора, кроме флагов VM и RF.
Пример 1
popf ;Регистр флагов загружается из стека
Пример 2
pushf ;Отправим флаги в стек
mov BP,SP ;Настроим ВР на флаги в стеке
or [BP],100h ;Установим бит 100h (флаг TF)
popf ;Вытолкнем в регистр флагов.
;Теперь в регистре флагов TF=1
386+ POPFD
Восстановление из стека расширенного регистра флагов
Команда popfd пересылает верхнее слово стека (на которое указывает регистр ESP) в расширенный регистр флагов EFLAGS. После этого содержимое ESP увеличивается на 4, и ESP указывает на предыдущее слово стека, которое теперь является его новой вершиной. Команда popfd не имеет параметров; она воздействует на все флаги процессора.
Пример
popfd ;Регистр EFLGS загружается из стека
PUSH Занесение операнда в стек
Команда push уменьшает на 2 содержимое указателя стека SP и заносит на эту новую вершину двухбайтовый операнд-источник (проталкивает в стек новое данное). Проталкивать в стек можно только целые слова (не байты). Программа должна строго следить за тем, чтобы каждой команде проталкивания в стек push отвечала обратная команда выталкивания из стека pop. Если стек используется для временного хранения некоторых данных, то извлекать эти данные из стека следует в порядке, обратном их сохранению.
В качестве операнда-источника может использоваться любой 16-разрядный регистр (включая сегментный) или ячейка памяти. Не допускается занесение в стек непосредственного значения, хотя некоторые трансляторы преобразуют команду вида
push 1234h
в неэффективную последовательность операций со стеком, результатом которой будет проталкивание указанного операнда в стек. Команда push не воздействует на флаги процессора.
Пара команд push — pop часто используется для пересылки данного из регистра в регистр (особенно, в сегментный) через стек.
Пример 1
push ES:mem ;Сохранение содержимого
push DS ;слова памяти mem из
push BP ;дополнительного сегмента
;а также регистров DS и ВР
… ;
pop PP ;Восстановление из стека
pop DS ;трех операндов
pop ES: mem ;в обратном порядке
Пример 2
push DS ;Пересылка DS через стек
pop ES ;Теперь ES=DS
386+ Допустима засылка в стек 32-битовых операндов (регистров и ячеек памяти), а также занесение в стек 8-, 16- и 32-битовых непосредственных значений. Каждое 8-битовое значение занимает в стеке целое слово. Операнды любого допустимого размера могут заноситься з стек вперемежку’, если это не вступает в противоречие с операциями по извлечению этих данных из стека.
Пример 1
push AX ; Сохранение в стеке регистра АХ
push 32h ;Сохранение в стеке
;константы 32h (она займет в
;стеке 1 слово)
push EAX ;Сохранение в стеке регистра
;ЕАХ (два слова стека)
386+ PUSHA Сохранение в стеке всех регистров
Команда pusha сохраняет в стеке содержимое всех регистров в следующем порядке: АХ, СХ, DX, ВХ, значение указателя стека SP перед выполнением данной команды, дачее ВР, SI и DI. Команда не имеет параметров и не воздействует на флаги процессора.
Пример
pusha
386+ PUSHAD Сохранение в стеке всех регистров в 32-разрядном режиме
Команда pushad сохраняет в стеке содержимое всех регистров в следующем порядке: EAX, ECX, EDX, ЕВХ, значение указателя стека ESP перед выполнением данной команды, далее EBP, ESI и EDI. Команда не имеет параметров и не воздействует на флаги процессора.
Пример
pushad
386+ PUSHFD Занесение в стек содержимого расширенного регистра флагов
Команда pushfd уменьшает на 4 содержимое указателя стека ESP и заносит на эту новую вершину содержимое расширенного регистра флагов EFALGS. При этом сохраняются все флаги процессора. Команда pushfd не имеет параметров и не воздействует на флаги процессора.
Пример
pushfd ;Содержимое регистра флагов
;сохраняется в стеке
RCL Циклический сдвиг влево через бит переноса
Команда гсl осуществляет сдвиг влево всех битов операнда. Если команда записана в формате
rcl операнд,1
сдвиг осуществляется на 1 бит. В младший бит операнда заносится значение флага CF; старший бит операнда загружается в CF. Если команда записана в формате
rcl операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда поступают сначала в CF, а оттуда — в младшие биты операнда (рис. П4).
В качестве операнда команды rcl можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги OF и CF.
Пример 1
clc ;Сбросим CF
mov AX, 7
rcl АХ,1 ‘ ;AX=000Eh=14, CF=0
Пример 2
stc ;Установим CF
mov DL,7
rcl DL,1 ;DL=0Fh=15, CF=0
Пример 3
clc ;Сбросим CF
mov BX,0FFFFh
rcl BX,1 ‘ ;BX=FFFEh, CF=1
Пример 4
clc ;Сбросим CF
mov DH,3
mov CL,4 ;Счетчик сдвигов
rcl DH,CL ;DH=30h=48, CF=0
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа битов сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov EAX,0С0000003h
clc ;Сбросим CF
rcl EAX,2 ;EAX=0000000Dh, CF=1
RCR Циклический сдвиг вправо через бит переноса
Команда rсl осуществляет сдвиг вправо всех битов операнда. Если команда записана в формате
rcl операнд,1
сдвиг осуществляется на 1 бит. В старший бит операнда заносится значение флага CF; младший бит операнда загружается в CF. Если команда записана в формате
rcl операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов младшие биты операнда поступают сначала в CF, а оттуда — в старшие биты операнда (Рис. П5).
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги OF и CF.
Пример 1
clc ;Сбросим флаг CF
mov AX, 2
rcr АХ,1 ;АХ=1, CF=0
Пример 2
stc ;Установим флаг CF
mov DL,8
rcr DL,1 ;DL=84h, CF=0
Пример 3
clc ;Сбросим флаг CF
mov BX,OFh
rcr BX,1 ;BX=7, CF=1
Пример 4
clc ;Сбросим флаг CF
mov DH,80h
mov CL,5 ;Счетчик сдвигов
rcr DH,CL ;DH=4, CF=0
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov ESI,0FFFF000lh
clc ;Сбросим флаг CF
rcr ESI,8 ;ESI=02FFFF00h, CF=0
Pentium+P RDMSR Чтение особого регистра модели
Команда читает содержимое внутреннего регистра, специфического для конкретной модели процессора.
REP Повторение
REPE Повторение пока равно
REPZ Повторение пока нуль
REPNE Повторение пока равно
REPNZ Повторение пока не равно
Префиксы повторения, позволяющие организовывать циклическое выполнение команд обработки строк cmps, movs и seas, и при этом проверять наличие указанного в префиксе условия.
Префикс rep, будучи установлен перед строковой командой movs или stos, заставляет ее выполняться СХ раз.
Префикс rере (и полностью эквивалентный ему префикс repz), будучи установлен перед строковой командой cmps или seas, заставляет ее выполняться до тех пор, пока результат выполнения равен 0 и, соответственно, ZF=1, но не более СХ раз.
Префикс rерnе (и полностью эквивалентный ему префикс repnz), будучи установлен перед строковой командой cmps или seas, заставляет ее выполняться до тех пор, пока результат выполнения не равен 0 и, соответственно, ZF=0, но не более СХ раз.
Примеры использования префиксов повторения см. в описаниях строковых команд cmps, movs и seas.
RET Возврат из процедуры
RETN Возврат из ближней процедуры
RETF Возврат из дальней процедуры
Команда ret извлекает из стека адрес возврата и передает управление назад в программу, первоначально вызвавшую процедуру. Если командой ret завершается ближняя процедура, объявленная с атрибутом near, или используется модификация команды retn, со стека снимается одно слово- относительный адрес точки возврата. Передача управления в этом случае осуществляется в пределах одного программного сегмента. Если командой ret завершается дальняя процедура, объявленная с атрибутом far, или используется модификация команды retf, со стека снимаются два слова: смещение и сегментный адрес точки возврата. В этом случае передача управления может быть межсегментной.
В команду ret может быть включен необязательный операнд (кратный 2), который указывает, на сколько байтов дополнительно смещается указатель стека после возврата в вызывающую программу. Прибавляя эту константу к новому значению SP, команда ret обходит аргументы, помещенные в стек вызывающей программой (для передачи процедуре) перед выполнением команды call. Обе разновидности команды не воздействуют на флаги процессора.
Пример 1
…
call subr ;Вызов подпрограммы
subr proc near
. . . ;Тело процедуры-подпрограммы
ret subr endp
Пример 2
push AX ;Параметр 1, передаваемый в
;подпрограмму
push SI ;Параметр 2, передаваемый в
;подпрограмму
call subr ;Вызов подпрограммы
…
subr proc near
…
;Извлечение из стека параметров
; (без изменения содержимого SP)
ret 4 ;Возврат в вызывающую
;программу и снятие со стека
;двух слов с параметрами
subr endp
ROL Циклический сдвиг влево
Команда rol осуществляет сдвиг влево всех битов операнда. Если команда записана в формате
rol операнд,1
сдвиг осуществляется на 1 бит. Старший бит операнда загружается в его младший разряд и одновременно заносится в флаг CF (рис. П6). Если команда записана в формате
rol операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда перемещаются в его младшие разряды. Последний перенесенный бит одновременно заносится в флаг CF.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги OF и CF.
Пример 1
mov AX,1
rol AX,1 ;AX=0002h, CF=0
Пример 2
mov DL,8 Oh
rol DL,1 ;DL=01h, CF=1
Пример 3
mov DX,3000h
mov CL,4
rol DX,CL ;DX=0003h, CF=1
Пример 4
mov DX,2000h
mov CL,4
rol DX,CL ;DX=0002h, CF=0
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov ЕАХ,012345678h
rol EАХ,16 ;EAX=56781234h
ROR Циклический сдвиг вправо
Команда ROR осуществляет циклический сдвиг вправо всех битов операнда. Если команда записана в формате
ror операнд,1
сдвиг осуществляется на 1 бит. Младший бит операнда записывается в его старший разряд и одновременно поступает в флаг CF (рис.Ш). Если команда записана в формате
ror операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов младшие биты операнда перемещаются в его старшие разряды. Последний перенесенный бит одновременно заносится в флаг CF.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги OF и CF.
Пример 1
mov AX,2
ror AX,1 ;AX=0001h, CF=0
Пример 2
mov DL,81h
ror DL,1 ;DL=C0h, CF=1
Пример 3
mov BX,000Eh
mov CL,4
ror BX,CL ;BX=E000h, CF=1
Пример 4
mov BX,0009h
mov CL,4
ror BX,CL ;BX=9000h, CF=1
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov EDI,90000001h
ror EDI,12 ;EDI=00190000h
SAHF Запись содержимого регистра АН в регистр флагов
Команда sahf копирует разряды 7, 6, 4, 2 и 0 регистра АН в регистр флагов процессора, устанавливая тем самым значения флагов SF, ZF, AF, PF и CF соответственно. Команда не имеет операндов.
Команда sahf (совместно с командой lahf) дает возможность читать и изменять значения флагов процессора, в том числе флагов SF, ZF, AF и PF, которые нельзя изменить непосредственно. Однако следует иметь в виду, что команда sahf заполняет только младший байт регистра флагов. Поэтому нельзя изменить с ее помощью, например, состояние флага OF.
Пример 1
lahf ;Регистр АН отображает
;состояние регистра флагов
or АН,80h ;Установка бита 7 = SF
sahf ;Загрузка АН в регистр
;флагов, где теперь будет SF = 1
Пример 2
lahf ;Регистр АН отображает
;состояние регистра флагов
and АН,0BFh ;Сброс бита 6 = ZF
sahf ;Загрузка АН в регистр
;флагов, где теперь будет ZF = О
Пример 3
mov АН, 5
sahf ;Устанавливаются флаги PF и
;CF и сбрасывается флаги SF,
;ZF и AF
SAL Арифметический сдвиг влево
Команда sal осуществляет сдвиг влево всех битов операнда. Старший бит операнда поступает в флаг CF. Если команда записана в формате
sal операнд, 1
сдвиг осуществляется на 1 бит. В младший бит операнда загружается 0. Если команда записана в формате
sal операнд,CL
сдвиг осуществляется на число битов, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда, пройдя через флаг CF, теряются, а младшие заполняются нулями (рис. П8.).
В качестве операнда команды sal можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение.
Каждый сдвиг влево эквивалентен умножению знакового числа на 2, поэтому команду sal удобно использовать для возведения операнда в степень 2.
Команда воздействует на флаги OF, SF, ZF, PF и CF.
Пример 1
mov AL,7
sal AL,1 ;AL= 0Eh=7*2, CF=0
Пример 2
mov AX,IFh
mov CL,8
sal AX,CL ;AX=lF00h=lFFh*256, CF=0
Пример 3
mov SI,-1 ;SI=FFFFh
mov CL,4
sal SI,CL ;SI=FFF0h=-l*16=-16, CF=1
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov EBX,0000C835h
sal EBX,5 ;EBX=001906A0h
SAR Арифметический сдвиг вправо
Команда sar осуществляет сдвиг вправо всех битов операнда. Младший бит операнда поступает в флаг CF. Если команда записана в формате
sar операнд,1
сдвиг осуществляется на 1 бит. Старший бит операнда сохраняет свое значение. Если команда записана в формате
sar операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов младшие биты операнда, пройдя через флаг CF, теряются, а старший бит расширяется вправо (рис. П9).
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение.
Каждый сдвиг вправо эквивалентен делению знакового числа на 2, поэтому команду sar удобно использовать для деления операнда на целые степени 2. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
mov AL,7
sar AL,1 ;AL=3=7/2, CF=1. Остаток
;потерян
Пример 2
mov AX,lFF0h
mov CL,4
sar AX,CL ;AX=01FFh=lFF0h/16, CF=0
Пример 3
mov BX,-8 ;BX=FFF8h
mov CL,2
sar BX,CL ;BX=FFFEh=-2=-8/4, CF=0
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример
mov EAX,0F0001234h
sar EAX,8 EAX=FFF00012h
SBB Целочисленное вычитание с займом
Команда sbb вычитает второй операнд (источник) из первого (приемника). Результат замещает первый операнд, предыдущее значение которого теряется. Если установлен флаг CF, из результата вычитается еще 1. Таким образом, если команду вычитания записать в общем виде
sbb операнд__1, операнд_2
то ее действие можно условно изобразить следующим образом:
операнд_1 — операнд_2 — CF -> операнд_1
В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команда sbb обычно используется для вычитания 32-разрядных чисел. Команда воздействует на флаги OF, SF, ZF, PF и CF.
Пример 1
mov AX,76A5h
sbb AX,76A3h ;AX=1, если CF был = 1
;AX=2, если CF был = 0
Пример 2
; В полях данных:
numlow dw 000Ah ;Младшая часть вычитаемого
numhigh dw 0001h ;Старшая часть вычитаемого
;Число 1000Ah=65546
;В программном сегменте:
mov AX, 0 ;Младшая часть уменьшаемого
mov DX,0002 ;Старшая часть уменьшаемого
;Число 20000h=131072
sub AX, numlow ;Вычитание младших частей.
;AX=FFF6h, CF=1
sbb DX,numhigh ;Вычитание старших частей с
;займом.
;DX:AX=0000:FFF6h=65526
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
;В полях данных:
nlow dd 0Ch ;Младшая часть вычитаемого
nhi dd 40000000h ;Старшая часть вычитаемого
;Число 400000000000000Ch ;В программном сегменте:
mov EAX,0Bh ;Младшая часть уменьшаемого
mov EBX,60000000h ;Старшая часть уменьшаемого
;Число 600000000000000Bh
sub EAX,nlow ;Вычитание младших частей.
;EAX=FFFFFFFFh, CF=1
sbb EBX,nhi ;Вычитание старших частей с
;займом. EBX=lFFFFFFFh
;Разность IFFFFFFFFFFFFFFFh
SCAS Сканирование строки с целью сравнения
SCASB Сканирование строки байтов с целью сравнения
SCASW Сканирование строки слов с целью сравнения
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они сравнивают содержимое регистра AL (в случае операций над байтами) или АХ (в случае операций над словами) с содержимым ячейки памяти по адресу, находящемуся в паре регистров ES:DI. Операция сравнения осуществляется путем вычитания содержимого ячейки памяти из содержимого AL или АХ. Результат операции воздействует на регистр флагов, но не изменяет ни один из операндов. Таким образом, операцию сравнения можно условно изобразить следующим образом:
АХ или AL — (ES:DI) ® флаги процессора
После каждой операции сравнения регистр DI получает положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1 или 2, в зависимости от размера сравниваемых элементов.
Вариант команды SCAS имеет формат
sсas строка
(что не избавляет от необходимости инициализировать регистры ES:DI адресом строки строка). Замена сегмента строки невозможна.
Рассматриваемые команды могут предваряться префиксами повторения repe/repz (повторять, пока элементы равны, т.е. до первого неравенства) и repne/repiiz (повторять, пока элементы не равны, т.е. до первого равенства). В любом случае выполняется не более СХ операций над последовательными элементами.
После выполнения рассматриваемых команд регистр DI указывает на ячейку памяти, находящуюся за тем (если DF=0) или перед тем (если DF=1) элементом строки, на котором закончились операции сравнения. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
;В полях данных сегмента данных, адресуемого через ES:
string db ‘ /Т:4’
;В программном сегменте:
сld ;Поиск вперед по строке
lea DI,string ;ES:DI ® string
mov AL, ‘ ‘ ;Символ, который мы пропускаем
mov CX,8 ;Длина строки repe scasb
;Поиск первого символа,
;отличного от пробела
je blank ;Символ не найден — одни пробелы
gotit: ;Продолжение, если символ найден
В примере 1 в строке имеются символы, отличные от искомого (кода пробела), и команда je выполнена не будет. После завершения сканирования управление будет передано на метку gotit. Содержимое регистров в этой точке: СХ=3 (так как не выполнено сканирование 3 символов), DI = <смещение string> + 5 (выполнено сканирование 5 символов). ES:D1 указывают на символ строки, следующий за отличным от пробела (в данном случае символ «Т»).
Пример 2
; В полях данных сегмента данных, адресуемого через ES:
string db ‘ /Т:4’
; В программном сегменте:
cld ;Поиск вперед по строке
lea DI,string ;ES:DI ® string
mov AL, ‘/’ ;Искомый символ
mov CX,8 ;Длина строки
repne scasb ;Поиск символа / в строке
jne blank ;Искомого символа нет
g’otit: ;Искомый символ найден
В примере 2 в строке имеется искомый символ («/»), и команда jne выполнена не будет. После завершения сканирования управление будет передано на метку gotit. Содержимое регистров в этой точке: СХ=3 (так как не выполнено сканирование 3 символов), DI = <смещение string> + 5 (выполнено сканирование 5 символов). ES:DI указывают на символ строки, следующий за найденным знаком «/» (в данном случае символ «Т»).
386+ SCASD
Сканирование строки двойных слов с целью сравнения
Команда аналогична командам МП 86 scab и scasw, но позволяет сравнивать содержимое расширенного регистра ЕАХ с двойным словом в памяти, адресуемым через регистры ES:EDI.
Пример
;В полях данных сегмента данных, адресуемого через ES:
nums dd 156000,432666,100000,0,4567890, …
;В программном сегменте:
cld ;Поиск вперед
mov DI,offset nums ;ES:DI -> nums
mov EAX,0 ;Искомое число
mov CX,10000 ;Максимальное число элементов
repne scasd ;Поиск 0 среди чисел массива
jne no0 ;Искомого числа нет
isO: ;Искомое число найдено
В примере в массиве чисел имеется искомое число 0 (с таким же успехом можно было искать любое другое число, например, 4567890). Команда jne выполнена не будет. После завершения сканирования управление будет передано на метку is0. Содержимое регистров в этой точке: СХ уменьшится на 4 (просмотрено 4 элемента), DI будет увеличено на 10h (4 числа по 4 байт в числе).
386+ SETcc Установка байта по условию
Команды, обозначаемые (в книгах, не в программах!) SETcc, осуществляют запись в указанный байтовый операнд 1 или 0 в зависимости от одного из 16 условий, определяемых флагами состояния. Если условие ее выполняется, команда записывает в операнд 1; если условие не выполняется — 0.В качестве операнда можно использовать байтовый регистр или 8-битовую ячейку памяти.
В составе команд процессора предусмотрены следующие команды условной установки байта:
Команда Установить 1, если Условие установки 1
seta выше CF=0 и ZF=0
setae выше или равно CF=0
setb ниже CF= I
setbe ниже или равно CF=1 или ZF=1
setc перенос CF=1
sete равно ZF=1
setg больше ZF=0 или SF=OF
setge больше или равно SF=OF
setl меньше SF не равно OF
setle меньше или равно ZF=1 или SF не равно ОР
setna не выше CF=1 или ZF=1
setnae не выше и не равно CF=1
setnb не ниже CF=0
setnbe не ниже и не равно CF=0 и ZF=0
setnc нет переноса CF=0
setne не равно ZF=0
setng не больше ZF=1 или SF не равно OF
setnge не больше и не равно SF не равно OF
setnl не меньше SF=OF
setnle не меньше и не равно ZF=0 и SF=OF
setno нет переполнения OF=0
setnp нет четности PF=0
setns знаковый бит равен О SF=0
setnz не нуль ZF=0
seto переполнение OF=1
setp есть четность PF=1
setpe сумма битов четная PF=1
setpo сумма битов нечетная PF=0
sets знаковый бит равен SF=1
setz нуль ZF= I
Команды, осуществляющие установку по условию «выше — ниже», предназначены для анализа чисел без знака; команды, осуществляющие установку по условию «больше — меньшее», предназначены для анализа чисел со знаком.
Пример 1
cmp AX,35h
seta CH ;Если AX>35h, CH=1
;Если AX<=35h, CH=0
Пример 2
; В полях данных
flag db ?
;В программном сегменте
test AX,8000h
sete flag ;Если в АХ установлен бит 7,
;flag=l. Иначе flag=0
386Р+ SGDT Сохранение в памяти содержимого регистра таблицы глобальных дескрипторов
Команда копирует содержимое регистра таблицы глобальных дескрипторов GDTR (линейный базовый адрес таблицы и ее границу) в поле из 6 байт, указанное в качестве операнда.
SHL Логический сдвиг влево
Команда полностью эквивалентна команде sal (арифметический сдвиг влево). См. описание команды sal.
386+ SHLD Логический сдвиг влево с двойной точностью
Трехоперандная команда shld с операндами op1, ор2 и орЗ осуществляет сдвиг влево первого из своих операндов opl. Число битов сдвига определяется третьим операндом орЗ. По мере сдвига операнда opl влево, выдвигаемые из него старшие биты, пройдя через флаг CF, теряются, ; на освобождающиеся места со стороны его младших битов поступают старшие биты второго операнда ор2, как если бы он вдвигался своим левым (старшим) концом в opl. Однако после завершения сдвига значение операнда ор2 не изменяется (рис. П10). Во флаге CF остается последний выдвинутый из операнда opl бит. Максимальное число битов сдвига составляет 31.
В качестве первого операнда op1можно указывать 16- или 32-разрядный регистр общего назначения или 16- или 32-битовую ячейку памяти. Вторым операндом ор2 может служить только 16- или 32-разрядный регистр общего назначения. Третий операнд, характеризующий число битов сдвига, может находиться в регистре CL или быть непосредственным значением.
Команда воздействует на флаги OF, SF, ZF, PF и CF.
Пример 1
mov AX,OC001h
mov BX,900Fh
shld AX,BX,1 ;AX=8003h, BX=900Fh, CF=1
Пример 2
mov AX,0C001h
mov BX,900Fh
shld AX,BX,2 ;AX=0006h, BX=900Fh, CF=1
Пример 3
mov AX,0C001h
mov BX,900Fh
shld AX,BX,3 ;AX=000Ch, BX=900Fh, CF=0
Пример 4
mov EBX,0FFCS000h
mov ESI,12340000h
mov CL,16
shld EBX,ESI,CL ;EBX=80001234h,
;ESI=12340000h, CF=0
SHR Логический сдвиг вправо
Команда shr осуществляет сдвиг вправо всех битов операнда. Младший бит операнда поступает в флаг CF. Если команда записана в формате
SHR операнд,1
сдвиг осуществляется на 1 бит. В старший бит операнда загружается 0, а младший теряется. Если команда записана в формате
SHR onepand,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда заполняются нулями, а младшие, пройдя через флаг CF, теряются (рис. П11).
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги CF, OF, PF, SF и ZF.
Пример 1
mov AL,7
shr AL,1 ;AL=3, CF=1
Пример 2
mov AX, lFF0h
mov CL,4
shr AX,CL ;AX=01FFh, CF=0
Пример 3
mov DX,9513h
mov CL,8
shr DX,CL ;DX=0095h, CF=0
386+ Допустим сдвиг 32-битовых операндов. Допустимо указание числа бит сдвига как с помощью регистра CL, так и непосредственным значением. Максимальная величина сдвига составляет 31 бит.
Пример 1
mov ESI,0FFFF0009h
shr ESI,8 ;ESI=00FFFF00h, CF=0
Пример 2
; В полях данных
mem dd 11111111h
;B программном сегменте
shr mem,12 ;mem=00011111h, CF=0
386+ SHRD Логический сдвиг вправо с двойной точностью
Трехоперандная команда shrd с операндами opl, ор2 и орЗ осуществляет сдвиг вправо первого из своих операндов opl. Число битов сдвига определяется третьим операндом орЗ. По мере сдвига операнда opl вправо выдвигаемые из него младшие биты, пройдя через флаг CF, теряются, а на освобождающиеся места со стороны его старших битов поступают младшие биты второго операнда ор2, как если бы он вдвигался своим правым (младшим) концом в opl. Однако после завершения сдвига значение операнда ор2 не изменяется (рис. П12). Во флаге CF остается последний выдвинутый из операнда opl бит. Максимальное число битов сдвига составляет 31.
В качестве первого операнда opl можно указывать 16- или 32-разрядный регистр общего назначения или 16- или 32-битовую ячейку памяти. Вторым операндом ор2 может служить только 16- или 32-разрядный регистр общего назначения.
Третий операнд, характеризующий число битов сдвига, может находиться в регистре CL или быть непосредственным значением.
Команда воздействует на флаги OF, SF, ZF, PF и CF.
Пример 1
mov AX,0C001h
mov BX,900Eh
shrd AX,BX,1 ;AX=6000h, BX=900Eh, CF=1
Пример 2
mov AX,0C001h
mov BX,900Eh
shrd AX,BX,2 ;AX=B000h, BX=900Eh, CF=0
Пример 3
mov AX,0C001h
mov BX,900Eh
shrd AX,BX,3 ;AX=D800h, BX=900Eh, CF=0
Пример 4
mov EBX,0FFCS000h
mov ESI,12345678h
mov CL,16
shrd EBX,ESI,CL ;EBX=5678FFC8h,
;ESI=12345678h, CF=0
386P+ SIDT Сохранение в памяти содержимого регистра таблицы дескрипторов прерываний
Команда копирует содержимое регистра таблицы дескрипторов прерываний IDTR (линейный базовый адрес таблицы и ее границу) в поле из 6 байт, указанное в качестве операнда.
386Р+ SLDT Сохранение содержимого регистра таблицы локальных дескрипторов
Команда копирует содержимое регистра таблицы локальных дескрипторов LDTR (селектор таблицы) в 16- или 32-разрядный регистр или в 16- или 32-битовое поле памяти, указанные в качестве операнда.
386Р+ SMSW Сохранение слова состояния машины
Команда smsw считывает слово состояния машины (так называется младшая половина управляющего регистра процессора CRO) и загружает его в указанный в команде 16-разрядный регистр общего назначения или 16-битовое поле памяти.
Команду srnsw можно использовать для перевода процессора из реального в защищенный режим или наоборот. В первом случае после чтения слова состояния командой smsw надо установить в нем бит 0 (бит РЕ) и загрузить назад в CRO командой Imsw. Во втором случае после после чтения слова состояния командой smsw надо сбросить в нем бит 0 и загрузить назад в CRO командой Imsw.
STC Установка флага переноса
Команда stc устанавливает флаг переноса CF в регистре флагов. Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
stc ;Флаг CF устанавливается
STD Установка флага направления
Команда STD устанавливает флаг направления DF в регистре флагов, определяя тем самым обратное направление выполнения строковых операций (в порядке убывания адресов элементов строки). Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
std ;Флаг направления устанавливается
STI Установка флага прерывания
Команда STI устанавливает флаг разрешения прерываний IF в регистре флагов, разрешая все аппаратные прерывания (от таймера, клавиатуры, дисков и т.д.). Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
sti ;Разрешение аппаратных прерываний
STOS Запись в строку данных
STOSB Запись байта в строку данных
STOSW Запись слова в строку данных
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они копируют содержимое регистра AL (в случае операций над байтами) или АХ (в случае операций над словами) в ячейку памяти соответствующего размера по адресу, определяемому содержимым пары регистров ES:DI. После операции копирования регистр DI получает положительное (если флаг DF=0) или отрицательное (если флаг DF=1) приращение. Величина приращения составляет 1 или 2 в зависимости от размера копируемого элемента.
Вариант команды stos имеет формат
stos строка
(что не избавляет от необходимости инициализировать регистры ES:DI адресом строки строка). Заменить сегментный регистр ES нельзя.
Рассматриваемые команды могут предваряться префиксом повторения rep. В этом случае они повторяются СХ раз, заполняя последовательные ячейки памяти одним и тем же содержимым регистра AL или АХ. Команда не воздействует на флаги процессора.
Пример 1
;В полях данных сегмента данных, адресуемого через ES:
id db ‘ID:’
;В программном сегменте:
eld ;Движение по строке вперед
mov DI,offset id+3;DI -> за знаком ‘:’
mov AL,’3′ ;Код ASCII цифры 3
stosb ;Отправим в строку
mov AL,’9′ ;Код ASCII цифры 9
stosb ;Отправим в строку
;Теперь в строке id записано ‘ID:39’
Пример 2
;В полях данных сегмента данных, адресуемого через ES:
array dw 10000 dup (?) ;Место под массив слов
; В программном сегменте:
mov AX,-1 ;Число-заполнитель
mov CX,10000 ;Заполнить 10000 слов
сld ;Движение по строке вперед
lea DI,array ;ES:DI ® array
rep stosw ;Bce 10000 элементов массива
;получают значение -1 (FFFFh)
Пример 3
;В полях данных сегмента данных, адресуемого через ES:
line db 80 dup (‘ ‘) ;Пустая пока строка
;В программном сегменте:
mov AL,’>’ ;Код ASCII знака ‘>’
mov CX,5 ;Заполнить 5 слов
eld ;Движение по строке вперед
lea DI,line ;ES:DI -» line
rep stos line ;Первые 5 байт строки line
;заполняются кодом ASCII
;знака ‘ >’
Пример 4
;В полях данных сегмента данных, адресуемого через ES:
line dw 80 dup (0) ;Строка, заполненная нулями
;В программном сегменте:
mov AL,’>’ ;Код ASCII знака ‘>’
mov AH,31h ;Атрибут (синий по бирюзовому)
mov CX,5 ; Заполнить 5 слов
сld ;Движение по строке вперед
lea DI,line ;ES:DI -» line
rep stos line ;Первые 5 слов строки line
;заполняются кодом ASCII
;знака ‘>’вместе с атрибутом
;для последующего вывода на экран
386+ STOSD Запись двойного слова в строку данных
Команда аналогична командам МП 86 stosb и stosw, но позволяет записать в строку, адресуемую через регистры ES:EDI, двойное слово из регистра ЕАХ.
Пример
; В полях данных
dat dd 12789,2,550000,100000
; В программном сегменте
mov ЕАХ,444777
push DS
pop ES ;ES=DS
mov DI, off set dat
add DI,4*2 ;DS:SI -» 3-й элемент массива
;чисел
stosd ;dat=12789,2,444777,100000
386P+ STR
Сохранение содержимого регистра состояния задачи
Команда str копирует содержимое регистра задачи TR (селектор сегмента состояния задачи) в двухбайтовый регистр общего назначения или 16-битовую ячейку памяти, указанные в качестве операнда.
SUB Вычитание целых чисел
Команда sub вычитает второй операнд (источник) из первого (приемника) и помещает результат на место первого операнда. Исходное значение первого операнда (уменьшаемое) теряется. Таким образом, если команду вычитания записать в общем виде
sub операнд_1, операнд_2
то ее действие можно условно изобразить следующим образом:
операнд_1 — операнд_2 -> операнд_1
В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример 1
mov AX,100
mov BX,60
sub АХ,ВХ ;АХ=40 (АХ-ВХ) , ВХ=60
Пример 2
mov DL, ‘8 ‘ mov DH, ‘0 ‘
sub DL,DH ;DL=8 (преобразование кода
; ASCII в цифру))
Пример 3
; ; В полях данных
datl dw -168
dat2 dw 10
; ; В программном сегменте
mov AX,data2
sub mem,AX ;mem = -178
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov EAX,1000000
mov EBX,60000
sub EAX,EBX ;EAX=40000
TEST Логическое сравнение
Команда test выполняет операцию логического умножения И над двумя операндами и, в зависимости от результата, устанавливает флаги SF, ZF и PF. Флаги OF и CF сбрасываются, a AF имеет неопределенное значение. Состояние флагов можно затем проанализировать командами условных переходов. Команда test не изменяет ни один из операндов.
В качестве первого операнда команды test можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака.
Правила побитового умножения:
Первый операнд-бит 0101
Второй операнд-бит 0011
Бит результата 0001
Флаг SF устанавливается в 1, если в результате выполнения команды образовалось число с установленным знаковым битом.
Флаг ZF устанавливается в 1, если в результате выполнения команды образовалось число, состоящее из одних двоичных нулей.
Флаг PF устанавливается в 1, если в результате выполнения команды образовалось число с четным количеством двоичных единиц в его битах.
Пример 1
test AX,1
jne bityes ;Переход, если бит 0 в АХ установлен
je bitno ;Переход, если бит 0 в АХ сброшен
Пример 2
test SI,8
jne bityes ;Переход, если бит 3 в SI установлен
je bitno ;Переход, если бит 0 в АХ сброшен
Пример 3
test DX,0FFFFh
jz null ;Переход, если DX=0
jnz smth ;Переход, если DX не 0
Пример 4
test CX,0F000h
jne bitsyes ;Переход, если какие-либо из
;4 старших битов СХ установлены
je bitsno ;Переход, если все 4 старших бита
; СХ сброшены
Пример 5
test AX,AX
jz zero ;Переход, если АХ=0
jnz notzero ;Переход, если АХ не 0
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
test ЕАХ,80000000h
jz b31 ;Переход, если бит 31 ЕАХ равен 0
jnz nob31 ;Переход, если бит 31 ЕАХ равен 1
386Р+ VERR Проверка сегмента на чтение
Команда verr позволяет определить, разрешено ли чтение из сегмента, за которым закреплен селектор, передаваемый команде в качестве ее операнда. Операндом может служить 16-разрядный регистр общего назначения или 16-битовая ячейка памяти.
386Р+ VERW Проверка сегмента на запись
Команда verw позволяет определить, разрешена ли запись в сегмент, за которым закреплен селектор, передаваемый команде в качестве ее операнда. Операндом может служить 16-разрядный регистр общего назначения или 16-битовая ячейка памяти.
486+ XADD Обмен и сложение
Команда xadd выполняет в одной операции сложение и обмен операндов. Команда требует двух операндов, причем первый операнд должен быть ячейкой памяти, а второй — регистром. После сложения операндов исходное содержимое памяти переносится во второй операнд (регистр), а полученная сумма записывается в память (на место первого слагаемого) (рис. П13). Команда воздействует на флаги OF, SF, ZF, AF, PF и CF.
Пример
; В полях данных
mem dw 99
;В программном сегменте
mov AX,48
xadd mem,AX ;mem=147, AX=99
XCHG Обмен данными между операндами
Команда xchg пересылает значение первого операнда во второй, а второго — в первый. В качестве любого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака. Команда не воздействует на флаги процессора.
Пример 1
mov AX,OFF01h
mov SI,1000h
xchg AX,SI ;AX=01000h, SI=FF01h
Пример 2
;В полях данных:
mem dw 0F0F0h
;В программном сегменте
mov CX,1256h
xchg CX,mem ;CX=F0F0h, mem=1256h
Пример 3
mov AX,6031h
xchg AH,AL ;AX=3160h
386+ Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
xchg ESI,EDI ;ESI и EDI обмениваются содержимым
XLAT Табличная трансляция
Команда xlat осуществляет выборку байта из массива байтов, который в этом случае называют таблицей трансляции. В регистре ВХ должен находиться относительный адрес таблицы, а в регистре AL — смещение в таблице к выбираемому байту (его индекс). Выбранный байт загружается в регистр AL, замещая находившееся в нем смещение. Длина таблицы может достигать 256 байт. Таблица должна находиться в сегменте данных, адресуемом через сегментный регистр DS. Замена сегмента не допускается. Команда xlat не имеет параметров, но требует предварительной настройки регистров ВХ и AL. Команда не воздействует на флаги процессора.
Пример
;Пример демонстрирует преобразование первых 14 скен-кодов
;(фактически это скен-коды клавиш верхнего ряда
;клавиатуры) в коды ASCII соответствующих символов
; В полях данных:
table db 0,27, ‘ 1234567890- = \’;Таблица кодов ASCII
;В программном сегменте
lea BX,table
mov AL,5 ;Скен-код 5 клавиши <4/$>
xlat ;AL=34h, код ASCII символа 4
386+ XLAT
Команда xlatb эквивалентна команде xlat МП 86 за исключением того, что для 32-разрядных приложений относительный адрес таблицы размещается в расширенном регистре ЕВХ.
Команда xlat может иметь в качестве операнда относительный адрес таблицы трансляции; в этом случае помещение адреса таблицы в регистр ЕВХ не требуется. Действие команды от этого не изменяется, однако возможна замена сегмента.
Пример
;В сегменте, адресуемом через сегментный регистр ES:
table db 0,27,’1234567890-=\’;Таблица кодов ASCII
;В программном сегменте
mov AL,13 ;Скен-код клавиши <=/+>
xlat ES:table ;AL=3Dh, код ASCII символа =
XOR Логическое ИСКЛЮЧАЮЩЕЕ ИЛИ
Команда хог выполняет операцию логического (побитового) ИСКЛЮЧАЮЩЕГО ИЛИ над своими двумя операндами. Результат операции замещает первый операнд; второй операнд не изменяется. Каждый бит результата устанавливается в 1, если соответствующие биты операндов различны, и сбрасывается в 0, если соответствующие биты операндов совпадают.
В качестве первого операнда команды хог можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго — регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами. Команда воздействует на флаги OF, SF, ZF, PF и CF, причем флаги OF и CF всегда сбрасываются, а остальные флаги устанавливаются в зависимости от результата.
Правила побитового ИСКЛЮЧАЮЩЕГО ИЛИ:
Первый операнд-бит 0101
Второй операнд-бит 0011
Бит результата 0110
Пример 1
mov AX,0Fh
хог AX,0FFFFh ;AX=FFF0h
Пример 2
хог ВХ,ВХ ;Обнуление ВХ
Пример 3
mov SI,0AAAAh
mov BX,5555h
xor SI,BX ;SI=FFFFh,BX=5555h
386+ Допустимо использование 32-битовьгх операндов и дополнительных режимов адресации 32-разрядных процессоров.
Пример
mov EAX,4444AAAAh
xor EAX,4441AAACh ;EAX=00050006h