Главная страница
Навигация по странице:

  • Команды над BCD-числами: Сложение неупакованных BCD-чисел

  • Вычитание неупакованных BCD-чисел

  • Умножение неупакованных BCD-чисел

  • Деление неупакованных BCD-чисел

  • Сложение упакованных BCD-чисел

  • Вычитание упакованных BCD-чисел

  • BCD-числа. Арифметические действия над двоичнодесятичными числами


    Скачать 27.54 Kb.
    НазваниеАрифметические действия над двоичнодесятичными числами
    АнкорBCD-числа
    Дата24.08.2022
    Размер27.54 Kb.
    Формат файлаdocx
    Имя файлаBCD-числа.docx
    ТипДокументы
    #652574

    Арифметические действия над двоично-десятичными числами

    Двоично-десятичные числа (Binary-Coded Decimal -BCD) могут представляться в двух форматах:

    • упакованном формате – каждый байт содержит две десятичные цифры.

    • неупакованный формат- каждый байт содержит одну десятичную цифру в четырех младших битах. Старшие четыре бита имеют нулевое значение.

    Команды над BCD-числами:

    Сложение неупакованных BCD-чисел

    Рассмотрим два случая сложения.

    Пример 1.

    Результат сложения не больше 9

    6 = 0000 0110

    +

    3 = 0000 0011

    =

    9 = 0000 1001

    Переноса из младшей тетрады в старшую нет. Результат правильный.
    Пример.2.

    Результат сложения больше 9:

    06 = 0000 0110

    +

    07 = 0000 0111

    =

    13 = 0000 1101

    Получили не BCD-число. Результат неправильный. Правильный результат в неупакованном BCD-формате должен быть таким: 0000 0001 0000 0011 в двоичном представлении (или 13 в десятичном).

    Для коррекции операции сложения двух однозначных неупакованных BCD-чисел в системе команд процессора существует специальная команда – AAA (ASCII Adjust for Addition) – коррекция результата сложения для представления в символьном виде.

    Эта команда не имеет операндов. Она работает неявно только с регистром al и анализирует значение его младшей тетрады:

    1) если это значение меньше 9, то флаг cf сбрасывается в 0 и осуществляется переход к следующей команде;

    2) если это значение больше 9, то выполняются следующие действия:

    а) к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;

    б) флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.

    Так, в примере 2, предполагая, что значение суммы 0000 1101 находится в al, после команды AAA в регистре будет 1101 + 0110 = 0011, т. е. двоичное 0000 0011 или десятичное 3, а флаг cf установится в 1, т. е. перенос запомнился. Далее нужно будет использовать команду сложения adc, которая учтет перенос из предыдущего разряда.
    Вычитание неупакованных BCD-чисел

    Ситуация здесь вполне аналогична сложению. Рассмотрим те же случаи.
    Пример

    Результат вычитания не больше 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-числа, необходимо:

    1) поместить один из сомножителей в регистр AL (по правилу команды mul);

    2) поместить второй операнд в регистр или память, отведя байт;

    3) перемножить сомножители командой mul (результат будет в ах);

    4) результат получится в двоичном коде, поэтому его нужно скорректировать.

    Для коррекции результата после умножения применяется специальная команда – AAM (ASCII Adjust for Multiplication) – коррекция результата умножения для представления в символьном виде.

    Алгоритм команды AAM:

    1) делит al на 10;

    2) результат деления записывается так: частное в al, остаток в ah. В результате после выполнения команды AAM в регистрах al и ah находятся правильные двоично-десятичные цифры произведения двух цифр.

    Эту команду можно применять для преобразования двоичного числа в регистре AL в неупакованное BCD-число, которое будет размещено в регистре ах: старшая цифра результата в ah, младшая – в al. Двоичное число должно быть в диапазоне 0… 99.
    Деление неупакованных BCD-чисел

    Коррекция осуществляться до основной операции, выполняющей непосредственно деление одного BCD-числа на другое BCD-число. Предварительно в регистре ах нужно получить две неупакованные BCD-цифры делимого. Далее нужно выполнить команду AAD – AAD (ASCII Adjust for Division) – коррекция деления для представления в символьном виде.

    Команда не имеет операндов и преобразует двузначное неупакованное BCD-число в регистре ах в двоичное число. Это двоичное число впоследствии будет играть роль делимого в операции деления. Кроме преобразования, команда AAD помещает полученное двоичное число в регистр AX. Делимое будет двоичным числом из диапазона 0… 99.

    Алгоритм, по которому команда AAD осуществляет это преобразование, состоит в следующем:

    1) умножить старшую цифру исходного BCD-числа в ах (содержимое АН) на 10;

    2) выполнить сложение АН + AL, результат которого (двоичное число) занести в AL;

    3) обнулить содержимое АН.

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

    Команду AAD можно использовать для перевода неупакованных BCD-чисел из диапазона 0… 99 в их двоичный эквивалент.

    Для деления чисел большей разрядности нужно реализовывать свой алгоритм, например «в столбик», либо найти более оптимальный путь.
    Сложение упакованных BCD-чисел

    Сложение упакованных BCD-чисел:

    67 = 01100111

    +

    75 = 01110101

    =

    142 = 1101 1100 = 220

    В двоичном виде результат равен 1101 1100 (или 220 в десятичном представлении), что неверно. Результат в двоично-десятичном виде должен быть равен 0001 0100 0010 (или 142 в десятичном представлении).

    Команда daa (Decimal Adjust for Addition) осуществляет коррекцию результата сложения для представления в десятичном виде.

    Пример 1

    mov AL, 87h ; Упакованное BCD 87

    add AL, 04h ; После сложения AL=8Bh

    daa ; AL=91h, т.е. упакованное BCD 91
    Пример 2

    mov AL, 87h ; Упакованное BCD 87

    add AL, 11h ; После сложения AL=97h

    daa ; AL=97h, т.е. упакованное BCD 97 (в данном случае команда daa ничего не делает)

    Пример 3

    mov AL, 71H ; AL = 0x71h

    add AL, 44H ; AL = 0x71h + 0x44h = 0xB5h

    daa ; AL = 0x15h

    ; CF = 1 - перенос является частью результата 71 + 44 = 115
    Вычитание упакованных BCD-чисел

    Выполним вычитание 67–75. Так как процессор выполняет вычитание способом сложения, то и мы последуем этому:

    67 = 01100111

    +

    -75 = 10110101

    =

    -8 = 0001 1100 = 28

    Результат равен 28 в десятичной системе счисления. В двоично-десятичном коде результат должен быть равен 0000 1000 (или 8 в десятичной системе счисления).

    Пример 1

    mov AL,55h ;Упакованное BCD 55

    sub AL,19h ;После вычитания AL=3Ch

    das ; AL=36h, т.е. упакованное BCD 36
    Пример 2

    mov AL,55h ;Упакованное BCD 55

    sub AL,15h ;После вычитания AL=40h

    das ; AL=40h, т.е. упакованное BCD 40 (в данном случае команда das ничего не делает)
    Пример

    .data

    Msg db "Программа", 0

    a db 4

    b db 2

    s db 0

    db 0

    .code

    prog:

    mov al, a

    mov bl, b

    add al, bl

    aaa

    or al, 30h

    mov s, al

    invoke MessageBox, NULL, addr s, addr Msg, MB_OK

    invoke ExitProcess, NULL

    end prog
    Пример

    .data

    Msg db "Программа", 0

    a db 4, 5

    b db 2, 7

    s db 2 dup(0)

    db 0

    .code

    prog:

    mov ebx, 1 ;

    clc

    pushf

    mov ecx, 2

    m1: mov al, a[ebx]

    popf

    adc al, b[ebx]

    aaa

    pushf

    or al, 30h

    mov s[ebx], al

    dec ebx

    loop m1

    popf

    invoke MessageBox, NULL, addr s, addr Msg, MB_OK

    invoke ExitProcess, NULL

    end prog
    Пример

    .data

    Msg db "Программа", 0

    a db 4, 5

    b db 2, 7

    s db 2 dup(0)

    db 0

    .code

    prog:

    mov ebx, 1

    clc

    pushf

    mov ecx, 2

    m1: mov al, a[ebx]

    popf

    sbb al, b[ebx]

    aas

    pushf

    or al, 30h

    mov s[ebx], al

    dec ebx

    loop m1

    popf

    invoke MessageBox, NULL, addr s, addr Msg, MB_OK

    invoke ExitProcess, NULL

    end prog


    написать администратору сайта