48264 (597389), страница 3
Текст из файла (страница 3)
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
.data
x1 db 0c2h
x2 db 022h
y db ?
.code
start:
mov ax,@data
mov ds,ax
mov al, x1
or al, x2
mov y, al
mov ax,4c00h
int 21h
end start
Арифметические операции над целыми двоичными числами
Сложение двоичных чисел без знака
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
add x2, ax
adc оп1,оп2 - команда сложения с учетом флага переноса cf. оп1 = оп1 + оп2 + знач_cf
Вычитание двоичных чисел без знака
dec операнд — операция декремента, то есть уменьшения значения операнда на 1;
dec cx ;cx:=cx-1
dec x
sub операнд_1,операнд_2 — команда вычитания; ее принцип действия:
операнд_1 = операнд_1 – операнд_2
sub al, 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
.data
x1 db 0c2h
x2 db 022h
y db ?
.code
start:
mov ax,@data
mov ds,ax
mov al, x1
add al, x2
mov y, al
mov ax,4c00h
int 21h
end start
Умножение двоичных чисел
mul множитель_1 - операция умножения двух целых чисел без учета знака
Алгоритм работы:
Команда выполняет умножение двух операндов без учета знаков. Алгоритм зависит от формата операнда команды и требует явного указания местоположения только одного сомножителя, который может быть расположен в памяти или в регистре. Местоположение второго сомножителя фиксировано и зависит от размера первого сомножителя
mul dl; ax:=al*dl, dl- множитель_1 , al- множитель_2
mul x1; dx:ax=ax*0ad91h, x1 word- множитель_1 , ax- множитель_2
mul ecx; edx:eax=eax*ecx, ecx- множитель_1 , eax- множитель_2
imul множитель_1 - операция умножения двух целочисленных двоичных значений со знаком
Деление двоичных чисел
div делитель - выполнение операции деления двух двоичных беззнаковых значений
Алгоритм работы:
Для команды необходимо задание двух операндов — делимого и делителя. Делимое задается неявно и размер его зависит от размера делителя, который указывается в команде
div dl ;ah:al=ax/dl, ax –делимое, dl- делитель , ah-частное, al -остаток
div x1 ;ax:dx=dx:ax/0ad91h, dx:ax –делимое, x1 word- делитель , ax-частное,
;dx -остаток
div ecx ;eax:edx=edx:eax/ecx, edx:eax –делимое, ecx- делитель , eax-частное,
;edx -остаток
idiv делитель - операция деления двух двоичных значений со знаком
Пример программы умножения двух однобайтных чисел.
model small
.stack 100h
.data
x1 db 78
yl db ?
yh db ?
.code
start:
mov ax,@data
mov ds,ax
xor ax, ax
mov al, 25
mul x1
jnc m1 ;если нет переполнения
mov yh,ah
m1:
mov yl, al
mov ax,4c00h
int 21h
end 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 ?
yc db ? ;частное
yo db ? ;остаток
.code
start:
mov ax,@data
mov ds,ax
mov ah,09h
mov dx, offset s1
int 21h ;вывод строки
mov ah,01h вводим х1
int 21h ;вводим число
sub al,30h ;al:=x1
mov x1,al
mov ah,09h
m ov dx, offset s2
int 21h
mov ah,01h вводим х2
int 21h
sub al,30h ;al:=x2
mov x2,al
mov ah,09h
m ov dx, offset s3
int 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
; можно вывести результат на экран
mov ax,4c00h
int 21h
end start
Команды сдвига
Все команды сдвига обеспечивают манипуляции над отдельными битами операндов, они перемещают биты в поле операнда влево или вправо в зависимости от кода операции.
Все команды сдвига устанавливают флаг переноса cf.
shl операнд,счетчик_сдвигов (Shift Logical Left) - логический сдвиг влево. Содержимое операнда сдвигается влево на количество битов, определяемое значением счетчик_сдвигов. Справа (в позицию младшего бита) вписываются нули;
shr операнд,счетчик_сдвигов — логический сдвиг вправо.
shl al, 2
Было al=00001101
Стало al=00110100
shr ax, 8
Было ax=4faf, стало ax=004f
mov cl,05h
shl bh, cl
bh=00010110
bh=11000000
shr x1,3

Алгоритм работы команд:
-
очередной “выдвигаемый” бит устанавливает флаг cf;
-
бит, вводимый в операнд с другого конца, имеет значение 0;
-
при сдвиге очередного бита он переходит во флаг cf, при этом значение предыдущего сдвинутого бита теряется!
sal операнд,счетчик_сдвигов (Shift Arithmetic Left)
sar операнд,счетчик_сдвигов
арифметический сдвиг влево/вправо. Содержимое операнда сдвигается влево/ вправо на количество битов, определяемое значением счетчик_сдвигов. Справа/ Слева в операнд вписываются нули.
Команда sal не сохраняет знака, но устанавливает флаг cf в случае смены знака очередным выдвигаемым битом. В остальном команда sal полностью аналогична команде shl;
Команда sar сохраняет знак, восстанавливая его после сдвига каждого очередного бита.
Команды циклического сдвига
rol операнд,счетчик_сдвигов (Rotate Left) — циклический сдвиг влево.
Содержимое операнда сдвигается влево на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые влево биты записываются в тот же операнд справа.
ror операнд,счетчик_сдвигов (Rotate Right) — циклический сдвиг вправо.
rol al, 3
Было al=10101100
Стало al=01100101
ror ax, 8
Было ax=4faf, стало ax=af4f
mov cl,05h
rol bh, cl
bh=00010110
bh=11000010
ror x1,2

Как видно из рис., команды простого циклического сдвига в процессе своей работы осуществляют одно полезное действие, а именно: циклически сдвигаемый бит не только вдвигается в операнд с другого конца, но и одновременно его значение становиться значением флага cf.
Команды циклического сдвига через флаг переноса cf отличаются от команд простого циклического сдвига тем, что сдвигаемый бит не сразу попадает в операнд с другого его конца, а записывается сначала в флаг переноса cf. Лишь следующее исполнение данной команды сдвига (при условии, что она выполняется в цикле) приводит к помещению выдвинутого ранее бита с другого конца операнда (см. рис. 4).
rcl операнд,счетчик_сдвигов (Rotate through Carry Left) — циклический сдвиг влево через перенос.
Содержимое операнда сдвигается влево на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса cf.
rcr операнд,счетчик_сдвигов (Rotate through Carry Right) — циклический сдвиг вправо через перенос.
Содержимое операнда сдвигается вправо на количество бит, определяемое операндом счетчик_сдвигов. Сдвигаемые биты поочередно становятся значением флага переноса cf.
Из рис. 4 видно, что при сдвиге через флаг переноса появляется промежуточный элемент, с помощью которого, в частности, можно производить подмену циклически сдвигаемых битов, в частности, рассогласование битовых последовательностей.
Под рассогласованием битовой последовательности здесь и далее подразумевается действие, которое позволяет некоторым образом локализовать и извлечь нужные участки этой последовательности и записать их в другое место
Пример. Дано отрицательное число. Выведите на экран его значение по модулю деленное на 2.
Любое отрицательное число хранится в дополнительном формате
-1 ffh
-2 feh
…
-10 f6h
получить значение числа по модулю, можно осуществив логическое отрицание над числом и добавив 1.
model small
.stack 100h
.data
x db -12
.code
start:
mov ax,@data
mov ds,ax
mov al,x ;в al отрицательное число
not al
inc al ;число по модулю
shr al,1
;выводим результат на экран
aam ;
;преобразование двоичного числа меньшего 63h (9910), которое находится в al в его ;неупакованный BCD-эквивалент
; -разделить значение регистра al на 10;
; -записать частное в регистр ah, остаток — в регистр al.
mov dx,ax ;число в регистр dx
or dx,3030h ;получаю ASCII код числа