4.4.5. Десятичная коррекция

Те же самые команды, что и для чисел в двоичном дополнительном коде, используются в программе для работы с числами в двоично-десятичном коде BCD. Однако результат арифметических операций может оказаться неправильным для двоично-десятичного представления. Команды десятичной коррекции корректируют результат, полученный после действий двоичной арифметики.

Десятичная коррекция для сложения DAA и десятичная коррекция для вычитания DAS используются для работы только с упакованными десятичными числами. В упакованном десятичном числе каждый байт содержит две десятичные цифры. Команды DAA и DAS работают только с байтом данных, содержащимся в регистре AL. В связи с этими присущими командам ограничени- ями, ни у DAA, ни у DAS операндов нет.

На Фиг. 4.12 показаны два примера. В первом примере складываются два упакованных десятичных числа. Оба числа состоят из двух десятичных цифр, поэтому они представлены единственными байтами. В примере складываются эти числа, оставляя результат в регистре AL. Непосредственно за этим следует команда DAA, которая корректирует результат сложения, преобразуя его в упакованную десятичную форму. После команды DAA в регистре AL остается правильное упакованное десятичное число в диапазоне 0 - 99. Если результат меньше 100, регистр содержит ответ, а флаг переноса содержит 0. Если результат находится в диапазоне 100 - 198, то в регистре AL остаются две младшие десятичные цифры, а флаг переноса установлен равным 1, показывая, что был перенос.


Microsoft (R) Macro Assembler Version 5.00                1/1/80 04:00:59
Фиг. 4.12 Пример двоично-десятичной арифметики                  Page  1-1
                         PAGE     ,132
                         TITLE    Фиг. 4.12 Пример двоично-десятичной арифметики
0000                     CODE     SEGMENT
                         ASSUME   CS:CODE,DS:CODE
0000    ??               BCD1     DB     ?         ; Две десятичные цифры упакованного числа
0001                     BCD2     DB     ?
0002    ????             BCD1L    DW     ?         ; Четыре десятичные цифры упакованного числа
0004    ????             BCD2L    DW     ?
0006                     FIG4_12 PROC    NEAR
                         ;-----   Сложение двух упакованных чисел
0006                     DAA_EXAMPLE:
0006    A0 0000 R                 MOV    AL, BCD1  ; Взять первое упакованное число
0009    02 06 0001 R              ADD    AL, BCD2  ; Добавить второе
000D    27                        DAA              ; Преобразование упакованного числа
000E    C3                        RET
                         ;-----   Сложение двух упакованных чисел размером по 4 цифры (2 байта)
000F                      DAA_LONG:
000F    A0 0002 R                 MOV    AL, BYTE PTR BCD1L
0012    02 06 0004 R              ADD    AL, BYTE PTR BCD2L  ; Добавление младшей части числа
0016    27                        DAA                        ; Коррекция упакованного числа
0017    A2 0004 R                 MOV    BYTE PTR BCD2L, AL  ; Сохранение младшей части
001A    A0 0003 R                 MOV    AL, BYTE PTR BCD1L+1

                        Фиг. 4.12 Примеры вычислений с BCD (начало)

001D    12 06 0005 R              ADC    AL, BYTE PTR BCD2L+1 ; Добавление старшей части числа
0021    27                        DAA                         ; Коррекция упакованного числа
0022    A2 0005 R                 MOV    BYTE PTR BCD2L+1, AL ; Сохранение старшей части
0025    C3                        RET
                         ;-----   Сложение двух упакованных чисел
0026                     DAS_EXAMPLE:
0026    A0 0000 R                 MOV    AL, BCD1
0029    2A 06 0001 R              SUB    AL, BCD2             ; Вычитание значений
002D    2F                        DAS                         ; Коррекция упакованного числа
002E    C3                        RET
002F                     FIG4_12 ENDP
002F                     CODE     ENDS
                         END

                      Фиг. 4.12 Примеры вычислений с BCD (продоложение)

Команда DAA правильно устанавливает регистр флагов. Если в результате сложения получилось значение в диапазоне 100 - 198, флаг переноса показывает перенос из старшей десятичной позиции. Аналогично, нулевой результат оставляет установленным в 1 флаг нуля. В случае операций с упакованными десятичными числами флаги знака и переполнения не имеют значения, хотя флаг знака устанавливается, если установлен старший бит регистра AL. Команда DAA использует флаг дополнительного переноса для определения вида коррекции, но после выполнения этой команды флаг дополнительного переноса неопределен.

Второй пример на Фиг. 4.12 демонстрирует десятичное сложение повышенной точности. Оно весьма похоже на двоичную арифметику с повышенной точностью, за исключением того, что после сложения каждого байта появляется команда DAA. Из-за ограничений, присущих команде DAA, в примере нельзя было сложить два упакованных десятичных слова, как слова, а затем применить коррекцию. С упакованными десятичными числами разрешена только байтовая арифметика.

Наконец, на Фиг. 4.12 показано, как использовать команду DAS. Это делается так же, как и при сложении, но команда DAS должна следовать за вычитанием. Здесь тоже допустимы только байтовые операции.