Иллюстрированный самоучитель по задачам и примерам Assembler

Двоичные числа. Сложение двоичных чисел.

Сложение с учетом знака чисел размером 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
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.