Двоичные числа. Сложение двоичных чисел.
Сложение с учетом знака чисел размером N байт
--------------------------------------------------------------------- :add_sign_N – процедура сложения с учетом знака чисел размером N байт -.Вход: summand_1и summand_2 – слагаемые. N – длина в байтах. :Выход: summand_1или carry+summand_1 – значение суммы с учетом переполнения. --------------------------------------------------------------------- .data summand_1db?:первое слагаемое N=$-summand_1:длина в байтах значений summand_1 и summand_2 carry db 0 расширение знака summand_2 db?:второе слагаемое .code add_sign_N proc mov cx.N mov si.0-1 cycl: incsi mov al,summand_2[si] adc summand_l[si].al loop cycl jc @@cfl_ofl jo @(acfO_ofl :cf=0 of=0 › результат верный:cf=1 of=0 › результат верный r_true :jmp end_p результат › summand_1@@cfl_ofl: jno?@cfl_of0:cf=1 of-1 › результат неверный mov carry.0ffh расширение знака д.б. =1. результат › sum_w jmp end_p @@cfl_of0::Cf"l of=0 › результат верный jmp r_true результат › summand_1@0cf0_ofl::cf=0 of=1 › результат неверный mov carry.0расширение знака д.б. =0. результат › sum_w jmp end_p end_p: ret add_sign_N endp
Сегмент данных может быть задан, например, так:
.data summand_1db 32.126,-120;первое слагаемое N=$-summand_1;длина в байтах значений summand_1 и sumniand_2 carry db 0 расширение знака summand_2 db 126.125,-120;второе слагаемое
Программа учитывает возможное переполнение результата. Обратите внимание на порядок задания значений слагаемого. Если слагаемое положительное, то проблем нет. Отрицательное слагаемое размером N байт для своего задания требует некоторых допущений. Старший байт отрицательного слагаемого задается со знаком и в процессе трансляции будет преобразован в значение, являющееся двоичным дополнением исходного значения. Остальные байты в своем исходном виде должны быть частью модуля. Поэтому для работы с числами со знаком удобно иметь программу, которая бы выполняла вычисление значения модуля отрицательного числа и, наоборот, по значению модуля вычисляла его дополнение.
Вычисление дополнения числа размером N байт
--------------------------------------------------------------------- : calc_complement – процедура вычисления дополнения числа размером N байт ;Вход: bx – адрес операнда в памяти; сх – длина операнда. ;Порядок следования байт – младший байт по младшему адресу.; Выход: bx – адрес результата в памяти --------------------------------------------------------------------- .code calc_complement proc хоr si,si neg byte ptr [bx] дополнение первого байта cmp byte ptr [bx],0;нулевой операнд – особый случай jne short $+3 stc установить cf, так как есть перенос dec ex jcxz @@ml;для однобайтного операнда @@cycl: iпс si not byte ptr [bx][si] adc byte ptr [bx][si],0 loop @@cycl @@ml: ret calc_complement endp
Для значений размерностью 1/2/4 байта дополнение можно получать с помощью одной команды NEG:
neg operand
Для значений N байт необходимо реализовывать алгоритм. Дополнение первого байта необходимо вычислять с учетом того, что он может быть нулевым. Попытка получить его дополнение с помощью команды NEG обречена на провал. Флаг CF в этом случае также должен устанавливаться программно. Подумайте, почему?
Вычисление модуля числа размером N байт
--------------------------------------------------------------------- :calc_abs – процедура вычисления модуля числа размером N байт :Вход: bx – адрес операнда в памяти; сх – длина операнда. ;Порядок следования байтов – младший байт по младшему адресу. :Выход: bx – адрес результата в памяти. --------------------------------------------------------------------- .code calc_abs proc определим знак операнда mov si.cx dec si test byte ptr [bx][si],80h проверяем знак операнда jz @@exit;число положительное call calc_complement @@exit:ret calc_abs endp