Связь с администрацией сайта:       

demo

Среди толпы я одинок

Глава 9 - арифметические команды процессора

Все арифметические команды устанавливают флаги CF, AF, SF, ZF, OF и PF в зависимости от результат операции. Применяются команды как к 16-ти так и к 32-х разрядным регистрам. Это относится практическик любым командам.
 
Команды арифметического сложения ADD и ADC
Команда ADD выполнят целочисленное сложение двух операндов, представленных в двоичном коде. Результат помещается на место первого операнда, второй операнд не изменяется. Команда корректирует регистр флагов в соответствии с результатом сложения. Существуют две формы сложения: 8-битовое и 16-битовое. В различных формах сложения принимают участие различные регистры. Компилятор следит за тем, чтобы операнды соответствовали друг другу. На следующих рисунках иллюстрируются различные варианты команды ADD. 
 
 ar com

Команда сложения с переносом ADC – это та же команда ADD, за исключением того, что в сумму включается флаг переноса CF, который прибавляется к младшему биту результата. Для любой формы команды ADD существует аналогичная ей команда ADC. Команда ADC часто выполняется как часть многобайтной или многословной операции сложения. 
Примеры использования команд ADD и ADC:
ADD AL,12h
ADD Count,1
ADC BX,4
ADD AX,BX
ADC Count,DI
Команды арифметического вычитания SUB и SBB
Команда вычитания SUB – идентична команде сложения, за исключением того, что она выполняет вычитание, а не сложение. Для нее верны предыдущие схемы, если в них поменять знак «+» на «–», т. е. она из первого операнда вычитает второй и помещает результат на место первого операнда. Команда вычитания также устанавливает флаги состояния в соответствии с результатом операции (флаг переноса здесь трактуется как заем). Команда вычитания с заемом SBB учитывает флаг заема CF, то есть значение заема вычитается из младшего бита результата.
 
Примеры использования команд SUB и SBB:
SUB AL,12h
SUB Count,1
SBB BX,4
SUB AX,BX
SBB Count,DI
Команда смены знака NEG
Команда отрицания NEG – оператор смены знака. Она меняет знак двоичного кода операнда – байта или слова.
Команды инкремента INC и декремента DEC
Команды инкремента и декремента изменяют значение своего единственного операнда на единицу. Команда INC прибавляет 1 к операнду, а команда DEC вычитает 1 из операнда. Обе команды могут работать с байтами или со словами. На флаги команды влияния не оказывают.
 
Команды умножения MUL и IMUL
Существуют две формы команды умножения. По команде MUL умножаются два целых числа без знака, при этом результат тоже не имеет знака. По команде IMUL умножаются целые числа со знаком. Обе команды работают с байтами и со словами, но для этих команд диапазон форм представления гораздо уже, чем для команд сложения и вычитания. На приведенных ниже рисунках представлены все варианты команд умножения.
 umn com
При умножении 8-битовых операндов результат всегда помещается в регистр AX. При умножении 16-битовых данных результат, который может быть длиною до 32 бит, помещается в пару регистров: в регистре DX содержатся старшие 16-бит, а в регистре AX – младшие 16-бит. Умножение не допускает непосредственного операнда.
Установка флагов командой умножения отличается от других арифметических команд. Единственно имеющие смысл флаги – это флаг переноса и переполнения.
Команда MUL устанавливает оба флага, если старшая половина результата не нулевая. Если умножаются два байта, установка флагов переполнения и переноса показывает, что результат умножения больше 255 и не может содержаться в одном байте. В случае умножения слов флаги устанавливаются, если результат больше 65535.
Команда IMUL устанавливает флаги по тому же принципу, т. е. если произведение не может быть представлено в младшей половине результата, но только в том случае если старшая часть результата не является расширением знака младшей. Это означает, что если результат положителен, флаг устанавливается как в случае команды MUL. Если результат отрицателен, то флаги устанавливаются в случае, если не все биты кроме старшего, равны 1. Например, умножение байт с отрицательным результатом устанавливает флаги, если результат меньше 128.
Примеры использования команд умножения:
MUL CX
IMUL Width
 
Команды деления DIV и IDIV
Как и в случае умножения, существуют две формы деления – одна для двоичных чисел без знака DIV, а вторая для чисел со знаком – IDIV. Любая форма деления может работать с байтами и словами. Один из операндов (делимое) всегда в два раза длиннее обычного операнда. Ниже приведены схемы, иллюстрирующие команды деления.
Байтовая команда делит 16-битовое делимое на 8-битовый делитель. В результате деления получается два числа: частное помещается в регистр AL, а остаток – в AH. Команда, работающая со словами, делит 32-битовое делимое на 16-битовый делитель. Делимое находится в паре регистров DX:AX, причем регистр DX содержит старшую значимую часть, а регистр AX – младшую. Команда деления помещает частное в регистр AX, а остаток в DX.
Ни один из флагов состояния не определен после команды деления. Однако, если частное больше того, что может быть помещено в регистр результата (255 для байтового деления и 65535 для деления слов), возникает ошибка значимости и выполняется программное прерывание уровня 0.
 delenie
Примеры использования команд деления:
IDIV CX
DIV Count
Практический пример
Вычислить значение арифметического выражения. Все числа являются 16-битовыми целыми со знаком. Формула вычислений следующая:
 formula
Эту задачу решает приведенная ниже программа. Здесь снова используются директивы определения сегментов а не модели памяти, ну во первых это только демонстрация, а реальные практические примеры мы рассмотрим далее. Фактически здесь отсутствует какой либо вывод на экран, однако суть применения команд должна стать понятной после рассмотрения этого примера.
;Сегмент стека
SSEG SEGMENT STACK 
DB 256 DUP(?)
SSEG ENDS
;Сегмент данных
DATA SEGMENT 
X DW ? ;Память для переменных
A DW ? 
B DW ?
C DW ?
D DW ?
DATA ENDS
;Сегмент кода
CODE SEGMENT 
ASSUME CS:CODE, DS:DATA, SS:SSEG
START: 
MOV AX,Data ;Инициализация DS
MOV DS,AX
;Вычислительная часть
MOV AX,2 ;Загрузка константы
IMUL A ;dx:ax = a*2
MOV BX,DX 
MOV CX,AX ;bx:cx = a*2
MOV AX,B
IMUL C ;dx:ax = b*c
ADD AX,CX
ADC DX,BX ;dx:ax = a*2+b*c
MOV CX,D
SUB CX,3 ;cx = d-3
IDIV CX ;ax = (a*2+b*c)/(d-3)
NEG AX ;ax = -ax
INC AX ;ax = ax+1
MOV X,AX ;Сохранение результата
MOV AH,4CH
INT 21H
CODE ENDS 
END START

На первом этапе программа выполняет два умножения. Так как результат умножения всегда помещается в пару регистров DX:AX, то в примере результат первого умножения переносится в пару регистров BX:CX перед выполнением второго умножения. Затем программа выполняет сложение числителя. Поскольку умножение дает 32-битовые результаты, в программе требуется сложение повышенной точности (с учетом флага переноса). После сложения результат остается в DX:AX (числитель). Знаменатель вычисляется в регистре CX, а затем на него делится числитель. Частное записывается в регистр AX, затем его знак меняется на обратный и к полученному значению прибавляется 1. На последнем этапе программа записывает результат из регистра AX в переменную X.
Остаток игнорируется.
 
 
Rate this item
(0 votes)
Login to post comments