Команды вычитания
К командам вычитания относятся следующие:
•sub операнд_1,операнд_2 — команда вычитания; ее принцип действия:
операнд_1 = операнд_1 – операнд_2
•sbb операнд_1,операнд_2 — команда вычитания с учетом заема (флага cf ):
(subtract with borrow -вычитание с заемом)
операнд_1 = операнд_1 – операнд_2 – значение_cf
флаг cf выполняет роль индикатора заема 1 из старшего разряда при вычитании чисел.
!!! Таким образом, после команды вычитания чисел без знака нужно анализировать состояние флага cf. Если он установлен в 1, то это говорит о том, что произошел заем из старшего разряда и результат получился в дополнительном коде.
•dec операнд — операция декремента, то есть уменьшения значения операнда на 1;
Пример 4. Проверка при вычитании чисел без знака
masm
model small
stack 256
.data
.code ;сегмент кода
main: ;точка входа в программу ...
xor ax,ax
mov al,5
sub al,10 ; вычитание - результат получается в дополнительном коде (отрицательный)
jnc m1 ;нет переноса?
neg al ;в al модуль результата
m1: ...
exit:
mov ax,4c00h ;стандартный выход
int 21h
end main ;конец программы
Для того чтобы преобразовать результат к нормальному виду (получить его модуль), применяется команда neg, с помощью которой получается дополнение операнда. В нашем случае мы получили дополнение дополнения или модуль отрицательного результата. А тот факт, что это на самом деле число отрицательное, отражен в состоянии флага cf. Дальше все зависит от алгоритма обработки.
2. Переполнения при операциях с числами со знаком и без знака
Помимо того, что процессор работает с двоичными числами, эти числа могут быть со знаком или без знака. Если число без знака, то оно просто представляет собой результат перевода десятичного числа в двоичный вид. Все биты в таком числе являются информационными и оно может принимать только неотрицательные значения.
Для представления чисел со знаком используется специальное кодирование. Старший бит в этом случае обозначает знак числа. Если знаковый бит равен нулю, то число положительное, иначе — отрицательное. Понятно, что положительное число со знаком будет выглядеть точно так же, как и число без знака.
С отрицательными числами чуть сложнее. Исторически для представления отрицательных чисел в компьютерах использовались разные виды кодирования: прямой, обратный и дополнительный код. В настоящее время наиболее часто используется дополнительный код, в том числе и в процессорах x86.
Чтобы сделать из положительного числа отрицательное, необходимо проинвертировать все его биты (0 заменяем на 1, а 1 заменяем на 0) и затем к младшему разряду прибавить единицу. Например, представим -5 в дополнительном коде:
Флаг переполнения OF - единственный флаг в старшем байте регистра флагов, который устанавливается обычными арифметическими операциями. Остальные флаги старшего байта находятся под прямым управлением программиста. Флаг переполнения - еще один арифметический флаг, как флаг нуля и переноса. Флаг переполнения необходим для арифметики в дополнительном коде в такой же степени, как флаг переноса для арифметики повышенной точности. В арифметике чисел, представленных в дополнительном коде, старший бит используется для хранения знака числа. Сумматор микропроцессора работает как со знакопеременными числами, так и беззнаковыми. Обычно сложение чисел со знаком дает верный результат. Однако накоторые из чисел, представленных в дополни- тельном коде, при сложении дают неверный результат. Пример на Фиг. 3.14 - сложение двух 8-битовых чисел, представленных в коде двоичного дополнения, - иллюстрирует этот случай. Если 72H и 53H - Шестнадцатеричное Десятичный эквивалент ------------------------------------------------ 72H 114 + 53H + 83 ------ ------ 0C5H 197 ------------------------------------------------ Фиг. 3.14 8-битовое сложение с переполнением числа без знака, то результат их сложения верен. Если же это числа, представленные в дополнительном коде со знаком, то результат сложения 0C5H неверен, в коде двоичного дополнения он равен -59. сложение положительных чисел никогда не дает в результате отри- цательное. Результат сложения оказался непредставиммым в диапазоне значений 8-битовых чисел в двоичном коде (от 127 до -128). Этот эффект принято называть переполнением, так как сумма вышла за пределы диапазона чисел, представимых в дополнительном коде. Важно заметить, что переполнение и перенос - два различных флага и имеют разное значение. На Фиг. 3.14 нет переноса, так как сложение без знака дает правильный результат, а есть переполнение: что сложение со знаком дает неверный результат. Возможен и случай одновременно переноса и переполнения, как показано на Фиг. 3.15. Шестнадцатеричное Двоичное дополнение Беззнаковое ------------------------------------------------------------ 8EH -114 142 0ADH - 83 173 ----- ----- ---- 1 3BH -197 315 ------------------------------------------------------------ Фиг. 3.15 8-битовое сложение с переносом и перепонением Здесь показан пример сложения двух отрицательных чисел. Результат -197 выходит за пределы диапазона представимости в дополнительном коде. Это показано тем, что 8-битовый результат 3BH - положительное число. Кроме того в этом примере устанавливается флаг переноса, означающий, что сложение без знака дало число, большее максимального представимого. В случае 8-битовых чисел максимальное число равно 255. Вообще говоря, операция сложения в процессоре выполняется одинаково над числами и со знаком, и без знака, а также с десятичными числами. Флаги переноса, дополнительного переноса и переполнения содержат информацию о выполненной операции, позволяя программе определить верный результат в используемой системе счисления. Флаг переполнения показывает, что результат арифметической операции выходит за пределы диапазона чисел, представленных в дополнительном виде. Переполнение отличается от переноса, который показывает, что произошел перенос из старшего бита результата.