Сложение BCD чисел (asm x86)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 19:58, 9 августа 2015.

Работай постоянно, не почитай работу для себя бедствием или бременем и не желай себе за это похвалы и участия. Общее благо — вот чего ты должен желать. МаркАарелий

Понятие о BCD-числах и элементарных действиях с ними приведены в главе 8 «Арифметические команды» учебника. В отличие от действий с двоичными чис¬лами работа с BCD-числами в процессоре реализована косвенно. В его системе команд нет инструкций, которые непосредственно выполняют основные арифметические действия над BCD-числами в том виде, как это делается для двоичных операндов. Тем более нет средств, которые каким-то образом учитывали бы знак. Все это должен делать сам программист. Ниже приведены макрокоманды, которые выполняют базовые арифметические операции над BCD-числами различной разрядности.

Неупакованные BCD-числа

Перед тем как приступать к работе с BCD-числами, необходимо договориться о том, как они будут представляться в оперативной памяти — старший байт BCD-числа по старшему адресу или старший байт BCD-числа по младшему адресу. Изменить фрагмент программы для поддержки того или иного способа представления чисел не представляет особого труда. Поэтому для однозначности рассуждений выберем естественный для процессоров Intel порядок следования байтов — младший байт по младшему адресу.

Сложение неупакованных BCD-чисел (макрокоманда)

;+-------------------------------------------------------------------------+
;| Макрокоманда: add_bcd summand_1. Сложение неупакованных BCD - чисел размером len_1 и len_2 байтов и помещение результата в sum. |
;+-------------------------------------------------------------------------+				
;| Вход: summand_1 и summand_2 - адреса младших байтов слагаемых: len_1 и len_2 - длины слагаемых в байтах. |
;+-------------------------------------------------------------------------+
;| Выход: sum - адрес младшего байта поля суммы. Желательно, чтобы это поле имело длину на единицу больше, чем длина самого длинного слагаемого.|
;+-------------------------------------------------------------------------+
;| Порядок следования байтов - младший байт по младшему адресу (Intel)|
;+-------------------------------------------------------------------------+
add_bcd       macro       summand_1. len_1. summand_2. len_2. sum
                 local         m1. m2. m3
                 push         si
                 push         bx
                 mov          ax. len_1
                 cmp          ax. len_2
                 jna            m2
                 mov          cx. len_1                  ; длина большего для сложение (см. ниже)
                 push         cx
                 mov          cx. len_2                  ; длина меньшего для сложение (см. ниже)
                 push         cx
                 mov          cx. ax
                 lea            bx. summand_1                  ; адрес большего источника для сложения
                 lea            bx. summand_2                  ; адрес меньшего источника для movsb
                 jmp           m3
m2:              mov          cx. len_2                    ; длина большего для сложение (см. ниже)
                 push         cx
                 mov          cx. len_1                 ; длина меньшего для сложение (см. ниже)
                 push         cx
                 mov          cx. len_2
                 lea            bx. summand_2                 ; адрес большего источника для сложения
                 lea            bx. summand_1                 ; адрес меньшего источника для movsb
m3:                                         ;------ заполняем sum нулями - длина определена выше
                 cld
                 xor           a1 .a1
                 lea            di. sum
                 rep           stosb
                                                ;------пересылка меньшего (по длине) BCD-числа в sum
                 cld
                 push         ds
                 pop          es
                 lea            di. sum                 ; адрес источнк см. выше
                 pop          cx                          ; длина была определена выше
                                                              ; и соответствует меньшему BCD-числу
                 rep           movsb  
                 pop          cx                         ; цикл по большему
                 xor           si. si
m1:              mov         a1. [bx][si]
                 adc          a1. sum[si]
                 aaa 
                 mov         sum[si].a1
                 inc           si
                 loop         m1
                 adc          sum[si]. 0
                 pop          bx 
                 pop          si
endm

Макрокоманда обрабатывает байты, исходя из предположения, что младший байт слагаемых находиться по младшему адресу. Слагаемые необязательно имеют одинаковую длину, но сумма должна иметь размер поля на единицу больше, чем длина самого длинного слагаемого. В начале процесса сложения в поле результата помещается меньшее (по длине) слагаемое.