команде;
2) если это значение больше 9, то выполняются следующие действия:
а) к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
б) флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.
Так, в примере 10, предполагая, что значение суммы 0000 1101 находится в al, после команды ааа в регистре будет 1101 + 0110 = 0011, т. е. двоичное 0000 0011 или десятичное 3, а флаг cf установится в 1, т. е. перенос запомнился в микропроцессоре. Далее программисту нужно будет использовать команду сложения adc, которая учтет перенос из предыдущего разряда.
Ситуация здесь вполне аналогична сложению. Рассмотрим те же случаи.
Пример
Результат вычитания не больше 9:
6 = 0000 0110
-
3 = 0000 0011
=
3 = 0000 0011
Как видим, заема из старшей тетрады нет. Результат верный и корректировки не требует.
Пример
Результат вычитания больше 9:
6 = 0000 0110
-
7 = 0000 0111
=
-1 = 1111 1111
Вычитание проводится по правилам двоичной арифметики. Поэтому результат не является BCD-числом.
Правильный результат в неупакованном BCD-формате должен быть 9 (0000 1001 в двоичной системе счисления). При этом предполагается заем из старшего разряда, как при обычной команде вычитания, т. е. в случае с BCD числами фактически должно быть выполнено вычитание 16 – 7. Таким образом, видно: как и в случае сложения, результат вычитания нужно корректировать. Для этого существует специальная команда – aas (ASCII Adjust for Substraction) – коррекция результата вычитания для представления в символьном виде.
Команда aas также не имеет операндов и работает с регистром al, анализируя его младшую тетраду следующим образом:
1) если ее значение меньше 9, то флаг cf сбрасывается в 0 и управление передается следующей команде;
2) если значение тетрады в al больше 9, то команда aas выполняет следующие действия:
а) из содержимого младшей тетрады регистра al (заметьте – не из содержимого всего регистра) вычитает 6;
б) обнуляет старшую тетраду регистра al;
в) устанавливает флаг cf в 1, тем самым фиксируя воображаемый заем из старшего разряда.
Понятно, что команда aas применяется вместе с основными командами вычитания sub и sbb. При этом команду sub есть смысл использовать только один раз, при вычитании самых младших цифр операндов, далее должна применяться команда sbb, которая будет учитывать возможный заем из старшего разряда.
На примере сложения и вычитания неупакованных чисел стало понятно, что стандартных алгоритмов для выполнения этих действий над BCD-числами нет и программист должен сам, исходя из требований к своей программе, реализовать эти операции.
Реализация двух оставшихся операций – умножения и деления – еще более сложна. В системе команд микропроцессора присутствуют только средства для производства умножения и деления одноразрядных неупакованных BCD-чисел.
Для того чтобы умножать числа произвольной размерности, нужно реализовать процесс умножения самостоятельно, взяв за основу некоторый алгоритм умножения, например «в столбик».
Для того чтобы перемножить два одноразрядных BCD-числа, необходимо:
1) поместить один из сомножителей в регистр AL (как того требует команда mul);
2) поместить второй операнд в регистр или память, отведя байт;
3) перемножить сомножители командой mul (результат, как и положено, будет в ах);
4) результат, конечно, получится в двоичном коде, поэтому его нужно скорректировать.
Для коррекции результата после умножения применяется специальная команда – aam (ASCII Adjust for Multiplication) – коррекция результата умножения для представления в символьном виде.
Она не имеет операндов и работает с регистром АХ следующим образом:
1) делит al на 10;
2) результат деления записывается так: частное в al, остаток в ah. В результате после выполнения команды aam в регистрах AL и ah находятся правильные двоично-десятичные цифры произведения двух цифр.
Перед окончанием обсуждения команды aam необходимо отметить еще один вариант ее применения. Эту команду можно применять для преобразования двоичного числа в регистре AL в неупакованное BCD- число, которое будет размещено в регистре ах: старшая цифра результата в ah, младшая – в al. Понятно, что двоичное число должно быть в диапазоне 0… 99.
Процесс выполнения операции деления двух неупакованных BCD-чисел несколько отличается от других, рассмотренных ранее операций с ними. Здесь также требуются действия по коррекции, но они должны осуществляться до основной операции, выполняющей непосредственно деление одного BCD-числа на другое BCD-число. Предварительно в регистре ах нужно получить две неупакованные BCD-цифры делимого. Это делает программист удобным для него способом. Далее нужно выдать команду aad – aad (ASCII Adjust for Division) – коррекция деления для представления в символьном виде.
Команда не имеет операндов и преобразует двузначное неупакованное BCD-число в регистре ах в двоичное число. Это двоичное число впоследствии будет играть роль делимого в операции деления. Кроме преобразования, команда aad помещает полученное двоичное число в регистр AL. Делимое, естественно, будет двоичным числом из диапазона 0… 99.
Алгоритм, по которому команда aad осуществляет это преобразование, состоит в следующем:
1) умножить старшую цифру исходного BCD-числа в ах (содержимое АН) на 10;
2) выполнить сложение АН + AL, результат которого (двоичное число) занести в AL;
3) обнулить содержимое АН.
Далее программисту нужно выдать обычную команду деления div для выполнения деления содержимого ах на одну BCD-цифру, находящуюся в байтовом регистре или байтовой ячейке памяти.
Аналогично ааш, команде aad можно найти и другое применение – использовать ее для перевода неупакованных BCD-чисел из диапазона 0… 99 в их двоичный эквивалент.
Для деления чисел большей разрядности, так же как и в случае умножения, нужно реализовывать свой алгоритм, например «в столбик», либо найти более оптимальный путь.
Как уже отмечалось выше, упакованные BCD-числа можно только складывать и вычитать. Для выполнения других действий над ними их нужно дополнительно преобразовывать либо в неупакованный формат, либо в двоичное представление. Из-за того, что упакованные BCD-числа представляют не слишком большой интерес, мы их рассмотрим кратко.