В ПК имеется несколько команд сложения и вычитания. Основными из них являются следующие:
В этих командах допустимы следующие комбинации операндов:
Команда ADD складывает операнды и записывает их сумму на место первого операнда: opl:=opl+op2. По команде SUB из первого операнда вычитается второй операнд и полученная разность записывается вместо первого операнда: opl:=opl-op2.
Например:
Мы уже рассмотрели особенности сложения и вычитания целых чисел, поэтому отметим лишь следующее. Команды ADD и SUB работают как с числами размером в байт, так и с числами размером в слово; нельзя, чтобы один операнд был байтом, а другой - словом. При этом числа могут быть как знаковыми, так и беззнаковыми. В этих командах меняются флаги переноса CF, переполнения OF, знака SF и нуля ZF (а также флаги AF и PF, но мы их не будем рассматривать), правила изменения которых мы уже рассмотрели.
Следующая пара команд сложения и вычитания:
увеличение на 1 (increment): INC op
уменьшение на 1 (decrement): DEC op
В этих командах допустимы следующие типы операнда: r8, m8, r16, m16.
Примеры:
INC BL
DEC WORD PTR A
Команда INC аналогична команде ADD op,1, т. е. увеличивает свой операнд на 1: ор1:=ор1+1, а команда DEC аналогична команде SUB op,1, т. е. уменьшает операнд на 1: opl:=op1-1 (единственное отличие: команды INC и DEC не меняют флаг переноса CF). Выгода от команд INC и DEC в том, что они занимают меньше места в памяти и выполняются быстрее, чем соответствующие команды ADD и SUB.
Еще одна команда из группы сложения и вычитания:
Изменение знака (negative): NEG op
Допустимые типы операнда этой команды: r8, m8, r16, m16. Команда NEG рассматривает свой операнд как число со знаком и меняет его знак на противоположный: ор:= -ор. Например:
MOV AH, 1
NEG АН;АН:= -1 (OFFh)
|
Здесь есть особый случай: если ор = -128 (80h)> то операнд не меняется, т. к. нет знакового числа +128. Аналогично для чисел-слов: если значение операнда равно минимальному отрицательному числу -32768 (8000h), то команда не меняет операнд.
В этом особом случае флаг OF получает значение 1 (при других операндах OF=0). При нулевом операнде флаг CF равен 0, при других - 1. Флаги SF и ZF меняются как обычно.
И, наконец, рассмотрим еще пару команд сложения и вычитания:
Сложение с учетом переноса (add with carry): ADC opl,op2
Вычитание с учетом заема (subtract with borrow): SBB opl,op2
Допустимые типы операндов - как в командах ADD и SUB. Эти команды аналогичны командам обычного сложения и вычитания (ADD и SUB) за одним исключением - в команде ADC к сумме операндов еще прибавляется значение флага переноса CF: opl:=opl+op2+CF, а в команде SBB из разности операндов еще вычитается значение этого флага: opl:=opl-op2-CF.
Зачем это нужно? В ПК одной командой можно сложить (вычесть) только числа размером в байт или слово. Сложение же (вычитание) чисел других размеров, например двойных слов, приходится реализовывать нам самим через сложение (вычитание) чисел размером в слово или байт. Здесь-то и оказываются полезными команды ADC и SBB.
Рассмотрим, для примера, как можно сложить следующие два числа размером в двойное слово: X=1204F003h и Y=8052300Fh. Условно разбиваем каждое число на два слова. Сначала складываем младшие (правые) части их, используя команду АDD. Может получиться единица переноса, которую надо учесть при сложении старших (левых) частей чисел. Как это сделать? Вспомним, что единица переноса попадает в флаг CF, поэтому к сумме старших частей надо добавить и значение этого флага (если единицы переноса не было, то CF=0, поэтому и здесь можно прибавлять CF), а такое сложение как раз и осуществляет команда ADC. Следовательно, старшие части чисел надо складывать по команде ADC.
|
Если для определенности считать, что число X размещается в двух регистрах АХ (старшие цифры) и ВХ (младшие), а число Y - в регистрах СХ (старшие цифры) и DХ (младшие), и если сумму этих двух чисел надо записать вместо числа X, т. е. надо реализовать (AX,BX):=(AX,BX)+(CX,DX), тогда это делается так:
ADD BX, DX;ВХ:=Хмл + Умл, CF = перенос
ADC AX, CX;AX:=Xст + Yст + CF
(Отметим, что при сложении старших частей также может появиться единица переноса, однако мы ее уже не будем учитывать.)
Аналогичным образом реализуется вычитание беззнаковых чисел размером в двойное слово, для чего используется команда SBB. Например, вычитание (AX,BX):= (AX,BX) - (CX,DX) реализуется так:
SUB BX,DX;ВХ:= Хмл - Умл, СР = заем единицы
SBB AX,CX;AX:= Xст – Yст – CF
С помощью команд ADC и SBB можно реализовать сложение и вычитание чисел любого размера, причем эти операции для беззнаковых и знаковых чисел реализуются одинаково.