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
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
; (остаток)
Рис.П3. Состояние стека после входа в подпрограмму и выполнения команды enter8,0(на рисунке адреса ячеек уменьшаются в низ)
Пример 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
INS Ввод строки из порта
INSB Ввод байта из порта
INSW Ввод слова из порта
INSD Ввод двойного слова из порта
Команды предназначены для ввода данных из порта непосредственно в память. Адрес порта указывается, как и для команды 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 какие-либо флаги процессора были установлены требуемым образом (весьма распространенный прием), их установку надо выполнить в копии флагов в стеке.
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 = О
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-разрядных процессоров.
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-разрядных процессоров. В защищенном режиме вместо сегментного адреса сегмента выступает его селектор.
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.
LODSW Загрузка слова из строки
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они загружают в регистр 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'
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
LSS Загрузка указателя с использованием регистра FS
Команды считывают из памяти полный указатель, состоящий из селектора и 16-битового или 32-битового смещения, и загружают младшую половину указателя (т.е. относительный адрес) в указанный в команде регистр общего назначения, а старшую половину указателя (т.е. селектор) в сегментный регистр, указанный в мнемонике команды.
В качестве первого операнда всех перечисленных команд указывается 16- или 32-разрядный регистр общего назначения; в качестве второго - ячейка памяти с 32- или 48-битовым содержимым. Команда не воздействует на флаги процессора.
Примеры см. в описании команд Ids и les.
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
MOVSB Пересылка байта данных из строки в строку
MOVSW Пересылка слова данных из строки в строку
Команды предназначены для операций над строками (строкой называется последовательность байтов или слов памяти с любым содержимым). Они пересылают по одному элементу строки, который может быть байтом или словом. Первый операнд (приемник) адресуется через 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 ;Перешлем все имя (от конца к началу)
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 выполняет вычитание целочисленного
Команда 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 ;Вывод в порт двойного слова
OUTSD Вывод двойного слова в порт
Команды предназначены для вывода данных в порт непосредственно из памяти. Адрес порта указывается, как и для команды 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-битовых данных
Pentium+ CMPXCHG8B Сравнение и обмен 8 байтов
Команда cmpxchgSb выполняет в одной операции сравнение и обмен 8-байтовых операндов. Команда требует один параметр и неявным образом использует еще два операнда - пары регистров EDX:EAX и ЕСХ:ЕВХ. В качестве явного операнда команды (приемника) может выступать только 64-битная (8-байтовая) ячейка памяти. Команда выполняет сравнение операнда-приемника в памяти с содержимым EDX:EAX. Если сравниваемые значения совпадают, то операнд-приемник в памяти замещается 64-битным значением ЕСХ:ЕВХ. Если сравниваемые значения не совпадают, содержимое памяти поступает в пару регистров EDXrEAX, замещая один из сравниваемых операндов (рис. П2). Команда воздействует на флаг ZF.
Рис. П2. Действие команды cmpxchg8b
Пример 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
Pentium+P RDMSR Чтение особого регистра модели
Команда читает содержимое внутреннего регистра, специфического для конкретной модели процессора.
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 ;Извлечение из стека двойного слова
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
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 ;Сохранение в стеке регистра
;ЕАХ (два слова стека)
RCL Циклический сдвиг влево через бит переноса
Команда гсl осуществляет сдвиг влево всех битов операнда. Если команда записана в формате
rcl операнд,1
сдвиг осуществляется на 1 бит. В младший бит операнда заносится значение флага CF; старший бит операнда загружается в CF. Если команда записана в формате
rcl операнд,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда поступают сначала в CF, а оттуда - в младшие биты операнда (рис. П4).
Рис. П4. Действие команды rcl.
В качестве операнда команды 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).
Рис. П.5. Действие команды rcl.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги 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
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.
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.
Рис. П6. Действие команды rol.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги 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.
Рис. П7. Действие команды ror.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги 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.).
Рис. П8. Действие команды sal.
В качестве операнда команды 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).
Рис. П9. Действие команды sar.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение.
Каждый сдвиг вправо эквивалентен делению знакового числа на 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
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 указывают на символ строки, следующий за найденным знаком "/" (в данном случае символ "Т").
SHL Логический сдвиг влево
Команда полностью эквивалентна команде sal (арифметический сдвиг влево). См. описание команды sal.
SHR Логический сдвиг вправо
Команда shr осуществляет сдвиг вправо всех битов операнда. Младший бит операнда поступает в флаг CF. Если команда записана в формате
SHR операнд,1
сдвиг осуществляется на 1 бит. В старший бит операнда загружается 0, а младший теряется. Если команда записана в формате
SHR onepand,CL
сдвиг осуществляется на число бит, указанное в регистре-счетчике CL, при этом в процессе последовательных сдвигов старшие биты операнда заполняются нулями, а младшие, пройдя через флаг CF, теряются (рис. П11).
Рис. П11. Действие команды shr.
В качестве операнда можно указывать любой регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда воздействует на флаги 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
Система команд процессоров 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, которому требуется использовать всю оперативную память компьютера. В настоящей книге, посвященной, в основном, реальному режиму, дается лишь перечисление привилегированных команд защищенного режима.
СМР Сравнение
Сами операнды не изменяются. Таким образом, если команду сравнения записать в общем виде
стр операнд_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< /FONT>
STC Установка флага переноса
Команда stc устанавливает флаг переноса CF в регистре флагов. Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
stc ;Флаг CF устанавливается
STD Установка флага направления
Команда STD устанавливает флаг направления DF в регистре
флагов, определяя тем самым обратное направление выполнения строковых операций (в порядке убывания адресов элементов строки). Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
std ;Флаг направления устанавливается
STI Установка флага прерывания
Команда STI устанавливает флаг разрешения прерываний IF в регистре флагов, разрешая все аппаратные прерывания (от таймера, клавиатуры, дисков и т.д.). Команда не имеет параметров и не воздействует на остальные флаги процессора.
Пример
sti ;Разрешение аппаратных прерываний
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
;знака '>'вместе с атрибутом
;для последующего вывода на экран
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
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
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