Двоично-десятичные числа (BCD-числа). Неупакованные BCD-числа.
Работай постоянно, не почитай работу для себя бедствием
или бременем и не желай себе за это похвалы и участия.
Общее благо – вот чего ты должен желать.
Марк Аврелий
Понятие о BCD-числах и элементарных действиях с ними приведены в уроке 8 "Арифметические команды" учебника. В отличие от действий с двоичными числами работа с BCD-числами в микропроцессоре реализована косвенно. В его системе команд нет инструкций, которые непосредственно выполняют основные арифметические действия над BCD-числами в том виде, как это делается для двоичных операндов. Тем более нет средств, которые каким-то образом учитывали бы знак. Все это должен делать сам программист. Ниже приведены макрокоманды, которые выполняют базовые арифметические операции над BCD-числами различной разрядности.
Перед тем как приступать к работе с BCD-числами, необходимо договориться о том, как будут представляться BCD-числа в оперативной памяти – старший разряд BCD-числа по старшему адресу или старший разряд BCD-числа по младшему адресу. Изменить фрагмент программы для поддержки того или иного способа представления чисел не представляет особого труда. Поэтому для однозначности рассуждений выберем естественный для микропроцессоров Intel порядок следования байтов – младший байт по младшему адресу.
Сложение неупакованных BCD-чисел (макрокоманда)
add_bcdmacro summand_i.1en_l,summand_2.1 en_2,sum local ml.m2.m3 :add_bcd summand_1.1en_l,summand_2.1en_2.sum – макрокоманда :сложения неупакованных BCD-чисел размером 1еп_1 и len_2 :байт и помещение результата в sum. :Вход: summand_i и summand_2 – адреса младших байтов слагаемых; 1еп_1 и 1еп__2 – длины слагаемых в байтах. ;Выход: sum – адрес младшего байта поля суммы. Желательно. :чтобы это поле имело длину на единицу больше, чем длина :самого длинного слагаемого. ;Порядок следования байт – младший байт по младшему адресу (Intel). push si push bx mov ax.len_l cmp ax.len_2 jna m2 mov cx,len_l;длина большего для сложения (см. ниже) push ex mov cx,len_2;длина меньшего для сложения (см. ниже) push ex mov cx.ax lea bx.summand_l:адрес большего источника для сложения lea si,summand_2:адрес меньшего источника для movsb jmp m3 т2: mov сх.1еп_2:длина большего для сложения (см. ниже) push ex mov cx.len_l;длина меньшего для сложения (см. ниже) push ex mov cx.len_2 lea bx.summand_2;адрес большего источника для сложения lea si.summand_l:адрес меньшего источника для movsb m3 : заполняем sum нулями – длина определена выше: eld хог al.al lea di .sum rep stosb;пересылка меньшего (по длине) BCD-числа в sum: eld push ds pop es lea di .sum:адрес источника см. выше pop сх;длина была определена выше и соотв. меньшему ВСО-числу rep movsb pop сх;дикл по большему хоr si,si ml: mov al.[bx][si] adc al, sum[si] aaa mov sum[si].al inc si loop ml adc sum[si].O pop bx pop si endm
Макрокоманда обрабатывает байты, исходя из предположения, что младший байт слагаемых находится по младшему адресу. Слагаемые необязательно имеют одинаковую длину, но сумма должна иметь размер поля на единицу больше, чем длина самого длинного слагаемого. В начале процесса сложения в поле результата помещается меньшее (по длине) слагаемое.
Нам понадобится и другой вариант этой команды – addbedr, который обрабатывает операнды с порядком следования байтов – старший байт по младшему адресу.