[Назад] [Далее]

2.3.3. Десятичная арифметика

Процессоры Intel поддерживают операции с двумя форматами десятичных чисел: неупакованное двоично-десятичное число — байт, принимающий значения от 00 до 09, и упакованное двоично-десятичное число — байт, принимающий значения от 00 до 99h. Все обычные арифметическиe операции над такими числами приводят к неправильным результатам. Например, если увеличить 19h на 1, то получится число 1Ah, а не 20h. Для коррекции результатов арифметических действий над двоично-десятичными числами используются следующие команды.

  • Команда:
  • DAA
  • Назначение:
  • BCD-коррекция после сложения
  • Процессор:
  • 8086

    Если эта команда выполняется сразу после ADD (ADC, INC или XADD) и в регистре AL находится сумма двух упакованных двоично-десятичных чисел, то в результате в AL записывается упакованное двоично-десятичное число, которое должно было быть результатом сложения. Например, если AL содержит число 19h, последовательность команд

        inc      al
        daa
    

    приведет к тому, что в AL окажется 20h (а не 1Ah, как было бы после INC).




    DAA выполняет следующие действия:

    • Если младшие четыре бита AL больше 9 или флаг AF = 1, то AL увеличивается на 6, CF устанавливается, если при этом сложении произошел перенос, и AF устанавливается в 1.
    • Иначе AF = 0.
    • Если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL увеличивается на 60h и CF устанавливается в 1.
    • Иначе CF = 0.

    Флаги AF и CF устанавливаются, если в ходе коррекции происходил перенос из первой или второй цифры соответственно, SF, ZF и PF устанавливаются в соответствии с результатом, флаг OF не определен.

  • Команда:
  • DAS
  • Назначение:
  • BCD-коррекция после вычитания
  • Процессор:
  • 8086

    Если эта команда выполняется сразу после SUB (SBB или DEC) и в регистре AL находится разность двух упакованных двоично-десятичных чисел, то в результате в AL записывается упакованное двоично-десятичное число, которое должно было быть результатом вычитания. Например, если AL содержит число 20h, последовательность команд

        dec      al
        das
    

    приведет к тому, что в AL окажется 19h (а не 1Fh, как было бы после DEC).




    DAS выполняет следующие действия:

    • Если младшие четыре бита AL больше 9 или флаг AF = 1, то AL уменьшается на 6, CF устанавливается, если при этом вычитании произошел заем, и AF устанавливается в 1.
    • Иначе AF = 0.
    • Если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL уменьшается на 60h и CF устанавливается в 1.
    • Иначе CF = 0.

    Известный пример необычного использования этой команды — самый компактный вариант преобразования шестнадцатеричной цифры в ASCII-код соответствующего символа (более длинный и очевидный вариант этого преобразования рассматривался в описании команды XLAT):

        cmp      al,10
        sbb      al,96h
        das
    

    После SBB числа 0 – 9 превращаются в 96h – 9Fh, а числа 0Ah – 0Fh — в 0А1h – 0A6h. Затем DAS вычитает 66h из первой группы чисел, переводя их в 30h – 39h, и 60h из второй группы чисел, переводя их в 41h – 46h.


    Флаги AF и CF устанавливаются, если в ходе коррекции происходил заем из первой или второй цифры соответственно, SF, ZF и PF устанавливаются в соответствии с результатом, флаг OF не определен.

  • Команда:
  • AAA
  • Назначение:
  • ASCII-коррекция после сложения
  • Процессор:
  • 8086

    Корректирует сумму двух неупакованных двоично-десятичных чисел в AL. Если коррекция приводит к десятичному переносу, АН увеличивается на 1. Эта команда имеет смысл сразу после команды сложения двух таких чисел. Например, если при сложении 05 и 06 в АХ окажется число 000Bh, то команда ААА скорректирует его в 0101h (неупакованное десятичное 11). Флаги CF и OF устанавливаются в 1, если произошел перенос из AL в АН, иначе они равны нулю. Значения флагов OF, SF, ZF и PF не определены.

  • Команда:
  • AAS
  • Назначение:
  • ASCII-коррекция после вычитания
  • Процессор:
  • 8086

    Корректирует разность двух неупакованных двоично-десятичных чисел в AL сразу после команды SUB или SBB. Если коррекция приводит к займу, АН уменьшается на 1. Флаги CF и OF устанавливаются в 1, если произошел заем из AL в АН, и в ноль — в противном случае. Значения флагов OF, SF, ZF и PF не определены.

  • Команда:
  • AAM
  • Назначение:
  • ASCII-коррекция после умножения
  • Процессор:
  • 8086

    Корректирует результат умножения неупакованных двоично-десятичных чисел, находящийся в АХ после выполнения команды MUL, преобразовывая полученный результат в пару неупакованных двоично-десятичных чисел (в АН и AL). Например:

        mov      al,5
        mov      bl,5      ; умножить 5 на 5
        mul      bl        ; результат в АХ - 0019h
        aam                ; теперь АХ содержит 0205h
    

    ААМ устанавливает флаги SF, ZF и PF в соответствии с результатом и оставляет OF, AF и CF неопределенными.




    Код команды ААМ — D4h 0Ah, где 0Ah — основание системы счисления, по отношению к которой выполняется коррекция. Этот байт можно заменить на любое другое число (кроме нуля), и ААМ преобразует АХ к двум неупакованным цифрам любой системы счисления. Такая обобщенная форма ААМ работает на всех процессорах (начиная с 8086), но появляется в документации Intel только с процессоров Pentium. Фактически действие, которое выполняет ААМ, — целочисленное деление AL на 0Ah (или любое другое число в общем случае), частное помещается в AL, и остаток — в АН, так что эту команду часто используют для быстрого деления в высокооптимизированных алгоритмах.


  • Команда:
  • AAD
  • Назначение:
  • ASCII-коррекция перед делением
  • Процессор:
  • 8086

    Выполняет коррекцию неупакованного двоично-десятичного числа, находящегося в регистре АХ, так, чтобы последующее деление привело к корректному десятичному результату. Например, разделим десятичное 25 на 5:

        mov      ax,0205h  ; 25 в неупакованном формате
        mov      bl,5
        aad                ; теперь в АХ находится 19h
        div      bl        ; АХ = 0005
    

    Флаги SF, ZF и PF устанавливаются в соответствии с результатом, OF, AF и CF не определены.




    Так же как и команда ААМ, AAD используется с любой системой счисления: ее код — D5h 0Ah, и второй байт можно заменить на любое другое число. Действие AAD состоит в том, что содержимое регистра АН умножается на второй байт команды (0Ah по умолчанию) и складывается с AL, после чего АН обнуляется, так что AAD можно использовать для быстрого умножения на любое число.



    п»ї
    "target=_blank><\/a>") //-->