То есть мы получили уже
Результат сложения больше 9
06 = 0000 0110 + 07 = 0000 0111 = 13 = 0000 1101
То есть мы получили уже не BCD-число. Результат неправильный. Правильный результат в неупакованном BCD-формате должен быть таким:
0000 0001 0000 0011 в двоичном представлении (или 13 в десятичном).
Проанализировав данную проблему при сложении BCD-чисел (и подобные проблемы при выполнении других арифметических действий) и возможные пути ее решения, разработчики системы команд микропроцессора решили не вводить специальные команды для работы с BCD-числами, а ввести несколько корректировочных команд.
Назначение этих команд — в корректировке результата работы обычных арифметических команд для случаев когда операнды в них являются BCD-числами.
В случае вычитания в примере 10 видно, что полученный результат нужно корректировать. Для коррекции операции сложения двух однозначных неупакованных BCD-чисел в системе команд микропроцессора существует специальная команда
aaa (ASCII Adjust for Addition) — коррекция результата сложения для представления в символьном виде.
Эта команда не имеет операндов. Она работает неявно только с регистром al и анализирует значение его младшей тетрады:
если это значение меньше 9, то флаг cf сбрасывается в 0 и осуществляется переход к следующей команде;
если это значение больше 9, то выполняются следующие действия:
к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.
Так, в примере 10, предполагая, что значение суммы 0000 1101 находится в al, после команды aaa в регистре будет 1101 + 0110= 0011, то есть двоичное 0000 0011 или десятичное 3, а флаг cf установится в 1, то есть перенос запомнился в микропроцессоре. Далее программисту нужно будет использовать команду сложения adc, которая учтет перенос из предыдущего разряда. Приведем пример программы сложения двух неупакованных BCD-чисел.
Листинг 8. Сложение неупакованных BCD-чисел <1> ;prg_8_8.asm <2> ... <3> .data <4> lenequ 2 ;разрядность числа <5> b db 1,7 ;неупакованное число 71 <6> c db 4,5 ;неупакованное число 54 <7> sum db 3 dup (0) <8> .code <9> main: ;точка входа в программу <10> ... <11> xor bx,bx <12> mov cx,len <13> m1: <14> mov al,b[bx] <15> adс al,c[bx] <16> aaa <17> mov sum[bx],al <18> inc bx <19> loop m1 <20> adc sum[bx],0 <21> ... <22> exit: |
В листинге 8 есть несколько интересных моментов, над которыми есть смысл поразмыслить. Начнем с описания BCD-чисел. Из строк 5 и 6 видно, что порядок их ввода обратен нормальному, то есть цифры младших разрядов расположены по меньшему адресу. Но это вполне логично по нескольким причинам:
во-первых, такой порядок удовлетворяет общему принципу представления данных для микропроцессоров Intel;
во-вторых, это очень удобно для поразрядной обработки неупакованных BCD-чисел, так как каждое из них занимает один байт.
Хотя, как уже было отмечено, программист сам волен выбирать способ описания BCD-чисел в сегменте данных. Строки 14–15 содержат команды, которые складывают цифры в очередных разрядах BCD-чисел, при этом учитывается возможный перенос из младшего разряда. Команда aaa в строке 16 корректирует результат сложения, формируя в al BCD-цифру и, при необходимости, устанавливая в 1 флаг cf. Строка 20 учитывает возможность переноса при сложении цифр из самых старших разрядов чисел. Результат сложения формируется в поле sum, описанном в строке 7.