· уменьшить значение указателя стека esp/sp на 4/2 (в зависимости от значения атрибута размера адреса — use16 или use32);
· записать источник в вершину стека (адресуемую парой ss:esp/sp).
Размер записываемых значений — слово или двойное слово. Также в стек можно записывать непосредственные значения. В стек можно класть значение сегментного регистра cs. Другой интересный момент связан с регистром sp. Команда push esp/sp записывает в стек значение esp/sp по состоянию до выдачи этой команды
Команда push используется совместно с командой pop для записи значений в стек и извлечения их из стека
pop cxpop bx
pop ax
push ax
pop bx ; аналогичнокоманде mov bx,ax
pusha - размещение в стеке регистров общего назначения в следующей последовательности: ax, cx, dx, bx, sp, bp, si, di
pushad- размещение в стеке регистров общего назначения в следующей последовательности: eax, ecx, edx, ebx, esp, ebp, esi, edi
pushf - размещение в вершине стека (ss:sp) содержимого регистра флагов flags
pushfd - размещение в стеке содержимого регистра флагов eflags.
popa- извлечение из стека регистров общего назначения di, si, bp, sp, bx, dx, cx, ax
popad - извлечение из стека регистров общего назначения edi, esi, ebp, esp, ebx, edx, ecx, eax
popf - извлечение из стека слова и восстановление его в регистр флагов flags
popfd - извлечение из стека двойного слова и восстановление его в регистр флагов eflags
Организация вычислений
Логические команды
Любая логическая команда меняет значение следующих флагов of, sf,zf,pf,cf (переполнение, знак, нуля, паритет, перенос)
and операнд_1,операнд_2 — операция логического умножения (И - конъюнкция).
оп1:=оп1 ٧оп2
and ah, 0a1h; ah:=ah٧0ah
and bx, cx; bx:=bx٧cx
and dx, x1; dx:=dx٧x1
orоперанд_1,операнд_2 — операция логического сложения (ИЛИ - дизъюнкцию)
or al, x1; оп1:=оп1 & оп2
or eax,edx
or dx, x1
xor операнд_1,операнд_2 — операция логического исключающего сложения (исключающего ИЛИ ИЛИ-НЕ)
testоперанд_1,операнд_2 — операция “проверить” (способом логического умножения).
Команда выполняет поразрядно логическую операцию И над битами операндов операнд_1 и операнд_2. Состояние операндов остается прежним, изменяются только флаги zf, sf, и pf, что дает возможность анализировать состояние отдельных битов операнда без изменения их состояния.
not операнд — операция логического отрицания. Команда выполняет поразрядное инвертирование (замену значения на обратное) каждого бита операнда. Результат записывается на место операнда.
Пример программы логического сложения двух однобайтных чисел.
model small.stack 100h.datax1 db 0c2hx2 db 022hy db ?.codestart:mov ax,@data mov ds,ax mov al, x1or al, x2mov y, al mov ax,4c00hint 21hendstart
Арифметические операции над целыми двоичными числами
Сложение двоичных чисел без знака
incоперанд - операция инкремента, то есть увеличения значения операнда на 1;
inc ax; ax:=ax+1
inc x1
addоп1,оп2 - команда сложения с принципом действия: оп1 = оп1 + оп2 (addition)
add al, bl
add ax, 0fe2h
add ebx, x1+2
add x1, 0fh
addx2, ax
adcоп1,оп2 - команда сложения с учетом флага переноса cf. оп1 = оп1 + оп2 + знач_cf
Вычитание двоичных чисел без знака
decоперанд — операция декремента, то есть уменьшения значения операнда на 1;
dec cx ;cx:=cx-1
dec x
subоперанд_1,операнд_2 — команда вычитания; ее принцип действия:
операнд_1 = операнд_1 – операнд_2
subal, bl; al:=al-bl
sub ax, x1
sub x2, dx
sub eax, 0f35h
sub x2, 22h
sbbоперанд_1,операнд_2 — команда вычитания с учетом заема (флага cf ):
операнд_1 = операнд_1 – операнд_2 – значение_cf
Пример программы сложения двух однобайтных чисел.
model small.stack 100h.datax1 db 0c2hx2 db 022hy db ?.codestart:mov ax,@data mov ds,ax mov al, x1 add al, x2 mov y, al mov ax,4c00h int 21hendstart
Умножение двоичных чисел
mulмножитель_1 - операция умножения двух целых чисел без учета знака
Алгоритм работы:
Команда выполняет умножение двух операндов без учета знаков. Алгоритм зависит от формата операнда команды и требует явного указания местоположения только одного сомножителя, который может быть расположен в памяти или в регистре. Местоположение второго сомножителя фиксировано и зависит от размера первого сомножителя
muldl; ax:=al*dl, dl- множитель_1 , al- множитель_2
mulx1; dx:ax=ax*0ad91h, x1 word- множитель_1 , ax- множитель_2
mulecx; edx:eax=eax*ecx, ecx- множитель_1 , eax- множитель_2
imul множитель_1 - операция умножения двух целочисленных двоичных значений со знаком
Деление двоичных чисел
divделитель - выполнение операции деления двух двоичных беззнаковых значений
Алгоритм работы:
Для команды необходимо задание двух операндов — делимого и делителя. Делимое задается неявно и размер его зависит от размера делителя, который указывается в команде
divdl ;ah:al=ax/dl, ax –делимое, dl- делитель , ah-частное, al -остаток
divx1 ;ax:dx=dx:ax/0ad91h, dx:ax –делимое, x1 word- делитель , ax-частное,
;dx -остаток
divecx ;eax:edx=edx:eax/ecx, edx:eax –делимое, ecx- делитель , eax-частное,
;edx -остаток
idivделитель - операция деления двух двоичных значений со знаком
Пример программы умножения двух однобайтных чисел.
model small.stack 100h.datax1 db 78yl db ?yh db ?.codestart:mov ax,@data mov ds,ax xor ax, ax mov al, 25 mulx1jncm1 ;если нет переполненияmov yh,ahm1: mov yl, al mov ax,4c00h int 21hend start
Пример. Вычислите следующее выражение у=(х2-х3)/х1, х1,х2,х3 - однобайтные числа
model small
.stack 100h
.data
s1 db 'Введитех1',10,13,'$'
s2 db 'Введите х2',10,13,'$'
s3 db 'Введите х3',10,13,'$'
x1 db ?
x2 db ?
ycdb ? ;частное
yo db ? ;остаток
.code
start:
mov ax,@data
mov ds,ax
mov ah,09h
mov dx, offset s1
int 21h ;вывод строки
movah,01h вводим х1
int 21h ;вводим число
subal,30h ;al:=x1
mov x1,al
mov ah,09h
mov dx, offset s2int 21h
movah,01h вводим х2
int 21h
sub al,30h ;al:=x2
mov x2,al
mov ah,09h
mov dx, offset s3int 21h
mov ah,01h вводимх3
int 21h
sub al,30h ;al:=x3
mov bl,x2 ;bl:=x2
sub bl,al ;bl:=x2-x3
xchg al,bl ;al:=bl, al:=x2-x3
xor ah,ah ;ax:=x2-x3 вычисляему
mov dl,x1 ;dl:=x1
div dl ;ax/dl, ax/x1
mov yc,ah
mov yo,al
; можно вывести результат на экран
movax,4c00h
int 21h
end start
Командысдвига
Все команды сдвига обеспечивают манипуляции над отдельными битами операндов, они перемещают биты в поле операнда влево или вправо в зависимости от кода операции.
Все команды сдвига устанавливают флаг переноса cf.
shlоперанд,счетчик_сдвигов (ShiftLogicalLeft) - логический сдвиг влево. Содержимое операнда сдвигается влево на количество битов, определяемое значением счетчик_сдвигов. Справа (в позицию младшего бита) вписываются нули;
shrоперанд,счетчик_сдвигов — логический сдвиг вправо.
Алгоритм работы команд:
· очередной “выдвигаемый” бит устанавливает флаг cf;
· бит, вводимый в операнд с другого конца, имеет значение 0;
· при сдвиге очередного бита он переходит во флаг cf, при этом значение предыдущего сдвинутого бита теряется!