Следующая подпрограмма может быть полезна для сдвига
содержимого pегистровой пары DX:AX вправо или влево. Можно
придумать более эффективный метод, но данный пример
представляет общий подход для любого числа циклов (и,
соответственно, сдвигов) в регистре CX. Заметьте, что сдвиг
единичного бита за разрядную сетку устанавливает флаг
переноса.

Сдвиг влево на 4 бита
MOV CX,04 ;Инициализация на 4 цикла
C20: SHL DX,1 ;Сдвинуть DX на 1 бит влево
SHL AX,1 ;Сдвинуть AX на 1 бит влево
ADC DX,00 ;Прибавить значение переноса
LOOP C20 ;Повторить
Сдвиг вправо на 4 бита
MOV CX,04 ;Инициализация на 4 цикла
D20: SHR AX,1 ;Сдвинуть AX на 1 бит вправо
SHR DX,1 ;Сдвинуть DX на 1 бит вправо
JNC D30 ;Если есть перенос,
OR AH,10000000B ; то вставить 1 в AH
D30: LOOP D20 ;Повторить

Ниже приведен более эффективный способ для сдвига влево,
не требующий организации цикла. В этом примере фактор сдвига
записывается в регистр CL. Пример написан для сдвига на 4
бита, но может быть адаптирован для других величин сдвигов:

MOV CL,04 ;Установить фактор сдвига
SHL DX,CL ;Сдвинуть DX влево на 4 бита
MOV BL,AH ;Сохранить AH в BL
SHL AX,CL ;Сдвинуть AX влево на 4 бита
SHL BL,CL ;Сдвинуть BL вправо на 4 бита



Ассемблер для IBM PC. Глава 12 271


OR DL,BL ;Записать 4 бита из BL в DL

ДЕЛЕНИЕ
------------------------------------------------------------

Операция деления для беззнаковых данных выполняется
командой DIV, a для знаковых - IDIV. Ответственность за
подбор подходящей команды лежит на программисте. Существуют
две основные операции деления:

Деление "слова на байт". Делимое находится в регистре AX,
а делитель - в байте памяти или а однобайтовом регистре.
После деления остаток получается в регистре AH, а частное -
в AL. Так как однобайтовое частное очень мало (максимально
+255 (шест.FF) для беззнакового деления и +127 (шест.7F) для
знакового), то данная операция имеет ограниченное
использование.

| AX | | AH | AL |
До деления: | Делимое| После: |Остаток|Частное|

Деление "двойного слова на слово". Делимое находится в
регистровой паре DX:AX, а делитель - в слове памяти или а
регистре. После деления остаток получается в регистре DX, а
частное в регистре AX. Частное в одном слове допускает
максимальное значение +32767 (шест.FFFF) для беззнакового
деления и +16383 (шест.7FFF) для знакового.

| DX || AX | | AH || AL |
До деления:|Ст.часть||Мл.часть| После:|Остаток||Частное|
| Делимое |

В единственном операнде команд DIV и IDIV указывается
делитель. Рассмотрим следующую команду:

DIV DIVISOR

Если поле DIVISOR определено как байт (DB), то операция
предполагает деление слова на байт. Если поле DIVISOR
определено как слово (DW), то операция предполагает деление
двойного слова на слово.
При делении, например, 13 на 3, получается разельтат 4
1/3. Частное есть 4, а остаток - 1. Заметим, что ручной
калькулятор (или программа на языке BASIC) выдает в этом
случае результат 4,333.... Значение содержит целую часть (4)
и дробную часть (,333). Значение 1/3 и 333... есть дробные
части, в то время как 1 есть остаток от деления.

Беззнаковое деление: Команда DIV

Команда DIV делит беззнаковые числа. На рис.12.5 в
процедуре D10DIV дано четыре примера деления: слово на байт,
байт на байт, двойное слово на слово и слово на слово.



Ассемблер для IBM PC. Глава 12 272


Первый пример команды DIV делит шест.2000 (8092) на шест.80
(128). В результате остаток 00 получается в регистре AH, а
частное шест.40 (64) - в регистре AL.
Второй пример команды DIV выполняет прежде расширение
байта BYTE1 до размеров слова. Так как здесь предполагается
беззнаковая величина, то в примере левый бит регистра AH
равен нулю. В результате деления остаток - шест. 12 получает
ся в регистре AH, а частное шест.05 - в регистре AL.
Третий пример команды DIV генерирует остаток шест. 1000 в
регистре DX и частное шест. 0080 в регистре AX.
В четвертом примере команды DIV сначала выполняется
расширение слова WORD1 до двойного слова в регистре DX.
После деления остаток шест.0000 получится в регистре DX, а
частное шест. 0002 - в регистре AX.

------------------------------------------------------------
------------------------------------------------------------
Рис.15.5. Беззнаковое и знаковое деление.

Знаковое деление: Команда IDIV

Команда IDIV (Integer DIVide) выполняет деление знаковых
чисел. На рис.12.5 в процедуре E10IDIV используются те же
четыре примера деления, что и в процедуре D10DIV, но вместо
команд DIV записаны команды IDIV. Первый пример команды
IDIV делит шест.2000 (положительное число) на шест.80 (отри
цательное число). Остаток от деления - шест. 00 получается в
регистре AH , а частное - шест. C0 (-64) - в регистре AL.
Команда DIV, используя те же числа, генерирует частное +64.
Шестнадцатиричные результаты трех остальных примеров
деления приведены ниже:

Пример команды IDIV Остаток Частное

2 EE (-18) FB (-5)
3 1000 (4096) 0080 (128)
4 0000 0002

Только в примере 4 вырабатывается такой же результат, что и
для команды DIV. Таким образом, если делимое и делитель
имеют одинаковый знаковый бит, то команды DIV и IDIV
генерируют одинаковый pезультат. Но, если делимое и делитель
имеют разные знаковые биты, то команда DIV генерирует положи
тельное частное, а команда IDIV - отрицательное частное.
Можно обнаружить это, используя отладчик DEBUG для трасси
ровки этих примеров.

Повышение производительности. При делении на степень
числа 2 (2, 4, и т.д.) более эффективным является сдвиг
вправо на требуемое число битов. В следующих примерах
предположим, что делимое находится в регистре AX:

Деление на 2: SHR AX,1



Ассемблер для IBM PC. Глава 12 273


Деление на 8: MOV CL,3
SHR AX,CL

Переполнения и прерывания

Используя команды DIV и особенно IDIV, очень просто
вызвать пеpеполнение. Прерывания приводят (по крайней мара
в системе, используемой при тестировании этих программ) к
непредсказуемым результатам. В операциях деления предполага
ется, что частное значительно меньше, чем делимое. Деление
на ноль всегда вызывает прерывание. Но деление на 1
генерирует частное, которое равно делимому, что может также
легко вызвать прерывание.
Рекомендуется использовать следующее правило: если
делитель - байт, то его значение должно быть меньше, чем
левый байт (AH) делителя: если делитель - слово, то его
значение должно быть меньше, чем левое слово (DX) делителя.
Проиллюстрируем данное правило для делителя, равного 1:

Операция деления: Делимое Делитель Частное
Слово на байт: 0123 01 (1)23
Двойное слово на слово: 0001 4026 0001 (1)4026

В обоих случаях частное превышает возможный размер. Для того
чтобы избежать подобных ситуаций, полезно вставлять перед
командами DIV и IDIV соответствующую проверку. В первом из
следующих примеpов предположим, что DIVBYTE - однобайтовый
делитель, а делимое находится уже в регистре AX. Во втором
примере предположим, что DIVWORD - двухбайтовый делитель, а
делимое находится в регистровой паре DX:AX.

Слово на байт Двойное слово на байт

CMP AH,DIVBYTE CMP DX,DIVWORD
JNB переполнение JNB переполнение
DIV DIVBYTE DIV DIVWORD

Для команды IDIV данная логика должна учитывать тот факт,
что либо делимое, либо делитель могут быть отрицательными, а
так как сравниваются абсолютные значения, то необходимо
использовать команду NEG для временного перевода
отрицательного значения в положительное.

Деление вычитанием

Если частное слишком велико, то деление можно выполнить с
помощью циклического вычитания. Метод заключается в том, что
делитель вычитается из делимого и в этом же цикле частное
увеличивается на 1. Вычитание продолжается, пока делимое
остается больше делителя. В cледующем примере, делитель
находится в регистре AX, а делимое - в BX, частное
вырабатывается в CX:




Ассемблер для IBM PC. Глава 12 274


SUB CX,CX ;Очистка частного
C20: CMP AX,BX ;Если делимое < делителя,
JB C30 ; то выйти
SUB AX,BX ;Вычитание делителя из делимого
INC CX ;Инкремент частного
JMP C20 ;Повторить цикл
С30: RET ;Частное в CX, остаток в AX

В конце подпрограммы регистр CX будет содержать частное,
а AX - oстаток. Пример умышленно примитивен для демонстрации
данной техники деления. Если частное получается в регистро
вой паре DX:AX, то необходимо сделать два дополнения:

1. В метке C20 сравнивать AX и BX только при нулевом DX.
2. После команды SUB вставить команду SBB DX,00.

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

ПРЕОБРАЗОВАНИЕ ЗНАКА
------------------------------------------------------------

Команда NEG обеспечивает преобразование знака двоичных
чисел из положительного в отрицательное и наоборот.
Практически команда NEG устанавливает противоположные
значения битов и прибавляет 1. Примеры:

NEG AX
NEG BL
NEG BINAMT (байт или слово в памяти)

Преобразование знака для 35-битового (или большего) числа
включает больше шагов. Предположим, что регистровая пара
DX:AX содержит 32-битовое двоичное число. Так как команда
NEG не может обрабатывать два регистра одновременно, то ее
использование приведет к неправильному результату. В следую
щем примере показано использование команды NOT:

NOT DX ;Инвертирование битов
NOT AX ;Инвертирование битов
ADD AX,1 ;Прибавление 1 к AX
ADC DX,0 ;Прибавление переноса к DX

Остается одна незначительная проблема: над числами,
представленными в двоичном формате, удобно выполнять арифме
тические операции, если сами числа определены в программе.
Данные, вводимые в программу с дискового файла, могут также
иметь двоичный формат. Но данные, вводимые с клавиатуры,
представленны в ASCII-формате. Хотя ASCII-коды удобны для
отображения и печати, они требуют специальных преобразований
в двоичный формат для арифметических вычислений. Но это уже
тема следующей главы.




Ассемблер для IBM PC. Глава 12 275


ПРОЦЕССОРЫ INTEL 8087 И 80287 ДЛЯ ОБРАБОТКИ ЧИСЛОВЫХ ДАННЫХ
------------------------------------------------------------

Системная плата компьютера содержит пустое гнездо,
зарезервированное для числового процессора Intel 8087 (или
80287). Сопроцессор 8087 действует совместно с 8088, а сопро
цессор 80287 действует совместно с 80286. Каждый сопроцессор
имеет собственный набор команд и средства для операций с
плавающей запятой для выполнения экспоненциальных,
логарифмических и тригонометрических функций. Сопроцессор
содержит восемь 80-битовых регистров с плавающей запятой,
которые могут представить числовые значения до 10 в 400 сте
пени. Математические вычисления в сопроцессоре выполняются
примерно в 100 раз быстрее, чем в основном процессоре.
Основной процессор выполняет специальные операции и
передает числовые данные в сопроцессор, который выполняет
необходимые вычисления и возвращает результат. Для ассембли
рования с помощью транслятора MASM, необходимо добавлять
параметр /E или /R, например, MASM /R.

ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
------------------------------------------------------------

ъ Будьте особенно внимательны при использовании однобайто
вых pегистров. Знаковые значения здесь могут быть от
-128 до +127.

ъ Для многословного сложения используйте команду ADC для
учета переносов от предыдущих сложений. Если операция
выполняется в цикле, то используя команду CLC,
установите флаг переноса в 0.

ъ Используйте команды MUL или DIV для беззнаковых данных
и команды IMUL или IDIV для знаковых.

ъ При делении будьте осторожны с переполнениями. Если
нулевой делитель возможен, то обеспечьте проверку этой
операции. Кроме того, делитель должен быть больше
содержимого регистра AH (для байта) или DX (для слова).

ъ Для умножения или деления на степень двойки используйте
cдвиг. Сдвиг вправо выполняется командой SHR для беззна
ковых полей и командой SAR для знаковых полей. Для
сдвига влево используются идентичные команды SHL и SAL.

ъ Будьте внимательны при ассемблировании по умолчанию.
Например, если поле FACTOR определено как байт (DB),
то команда MUL FACTOR полагает множимое в регистре AL,
а команда DIV FACTOR полагает делимое в регистре AX.
Если FACTOR определен как слово (DW), то команда MUL
FACTOR полагает множимое в регистре AX, а команда DIV
FACTOR полагает делимое в регистровой паре DX:AX.




Ассемблер для IBM PC. Глава 12 276


ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
------------------------------------------------------------

Все вопросы имеют отношение к следующим данным:

DATAX DW 0148H
DW 2316H
DATAY DW 0237H
DW 4052H

12.1. Закодируйте команды для сложения а) слова DATAX со
словом DATAY; б) двойного слова, начинающегося по
адресу DATAX, с двойным словом в DATAY.

12.2. Объясните действие следующих команд:

STC
MOV BX,DATAX
ADC BX,DATAY

12.3. Закодируйте команды для умножения (MUL): а) слова
DATAX на слово DATAY; б) двойного слова , начинающего
ся по адресу DATAX, на слово DATAY.

12.4. Какой делитель, кроме нуля, вызывает ошибку
переполнения?

12.5. Закодируйте команды для деления (DIV): а) слова DATAX
на 23; б) двойного слова, начинающегося по адресу
DATAX, на слово DATAY.

12.6. Последний пример в разделе "Сдвиг регистроврй пары
DX:AX" является более эффективным по сравнению с
предыдущими примерами для сдвига влево на четыре бита.
Измените пример для сдвига вправо на четыре бита.





















Ассемблер для IBM PC. Глава 13 1



    ГЛАВА 13. Арифметические операции II:


------------------------------------------------------------

Арифметические операции II:
Обработка данных в форматах ASCII и BCD

Цель: Рассмотреть ASCII и BCD форматы данных и дать сведения
о преобразованиях между этими форматами и двоичным форматом.

ВВЕДЕНИЕ
------------------------------------------------------------

Для получения высокой производительности компьютер
выполняет aрифметические операции над числами в двоичном
формате. Как показано в главе 12, этот формат не вызывает
особых трудностей, если данные определены в самой программе.
Во многих случаях новые данные вводятся программой с
клавиатуры в виде ASCII символов в деcятичном формате.
Аналогично вывод информации на экран осуществляется в
кодах ASCII. Например, число 23 в двоичном представлении
выглядит как 00010111 или шест.17; в коде ASCII на каждый
cимвол требуется один байт и число 25 в ASCII-коде имеет
внутpеннее представление шест.3235.
Назначение данной главы - показать технику преобразования
данных из ASCII-формата в двоичный формат для выполнения
арифметических операций и обратного преобразования двоичных
результатов в ASCII-формат для вывода на экран или принтер.
Программа, приведенная в конце главы , демонстрирует большую
часть матеpиала от главы 1 до главы 12.
При программировании на языках высокого уровня, таких как
BASIC или Pascal, для обозначения порядка числа или положе
ния десятичной запятой (точки) можно положиться на
кампилятор. Однако, компьютер не распознает десятичную
запятую (точку) в арифметических полях. Так как двоичные
числа не имеют возможности установки десятичной (или
двоичной) запятой (точки), то именно программист должен
подразумевать и определить порядок обрабатываемых чисел.

ASCII-формат
------------------------------------------------------------

Данные, вводимые с клавиатуры, имеют ASCII-формат,
например, буквы SAM имеют в памяти шестнадцатиричное
представление 53414D, цифры 1234 - шест. 31323334. Во многих
случаях формат алфавитных данных, например, имя человека
или описание статьи, не меняется в программе. Но для
выполнения арифметических операций над числовыми значениями,
такими как шест. 31323334, требуется специальная обработка.
С помощью следующих ассемблерных команд можно выполнять
арифметические операции непосредственно над числами в
ASCII-формате:




Ассемблер для IBM PC. Глава 13 2


AAA (ASCII Adjust for Addition -
коррекция для сложения ASCII-кода)
AAD (ASCII Adjust for Division -
коррекция для деления ASCII-кода)
AAM (ASCII Adjust for Multiplication -
коррекция для умножения ASCII-кода)
AAS (ASCII Adjust for Subtraction -
коррекция для вычитания ASCII-кода)

Эти команды кодируются без операндов и выполняют автоматичес
кую коррекцию в регистре AX. Коррекция необходима, так как
ASCII код представляет так называемый распакованный
десятичный формат, в то время, как компьютер выполняет
арифметические операции в двоичном формате.

Сложение в ASCII-формате

Рассмотрим процесс сложения чисел 8 и 4 в ASCII-формате:

Шест. 38
34
Шест. 6C

Полученная сумма неправильна ни для ASCII-формата, ни для
двоичного формата. Однако, игноригуя левую 6 и прибавив 6 к
правой шест.C: шест.C + 6 = шест.12 - получим правильный
результат в десятичном формате. Правильный пример слегка
упрощен, но он хорошо демонстрирует процесс, который выполня
ет команда AAA при коррекции.
В качестве примера, предположим, что регистр AX содержит
шест. 0038, а регистр BX - шест.0034. Числа 38 и 34
представляют два байта в ASCII формате, которые необходимо
сложить. Сложение и коррекция кодируется следующими
командами:

ADD AL,BL ;Сложить 34 и 38
AAA ;Коррекция для сложения ASCII кодов

Команда AAA проверяет правую шест. цифру (4 бита) в регистре
AL. Если эта цифра находится между A и F или флаг AF равен
1, то к регистру AL прибавляется 6, а к регистру AH
прибавляется 1, флаги AF и CF устанавливаются в 1. Во всех
случаях команда AAA устанавливает в 0 левую шест. цифру в
регистре AL. Результат - в регистре AX:

После команды ADD: 006C
После команды AAA: 0102

Для того, чтобы выработать окончательное ASCII-представ
ление, достаточно просто поставить тройки на место левых
шест. цифр:
OR AX,3030H ;Результат 3132




Ассемблер для IBM PC. Глава 13 3


Все показанное выше представляет сложение однобайтовых
чисел. Сложение многобайтовых ASCII-чисел требует организа
ции цикла, который выполняет обработку справа налево с
учетом переноса. Пример , показанный на рис.13.1 складывает
два трехбайтовых ASCII-числа в четырехбайтовую сумму.
Обратите внимание на следующее:

ъ В программе используется команда ADC, так как любое
сложение может вызвать перенос, который должен быть
прибавлен к следующему (слева) байту. Команда CLC
устанавливает флаг CF в нулевое состояние.

------------------------------------------------------------
------------------------------------------------------------
Рис. 13.1. Сложение в ASCII-формате.

ъ Команда MOV очищает регистр AH в каждом цикле, так как
команда AAA может прибавить к нему единицу. Команда
ADC учитывает пеpеносы. Заметьте, что использование
команд XOR или SUB для oчистки регистра AH изменяет
флаг CF.
ъ Когда завершается каждый цикл, происходит пересылка
содержимого pегистра AH (00 или 01) в левый байт
суммы.
ъ В результате получается сумма в виде 01020702. Програм
ма не использует команду OR после команды AAA для
занесения левой тройки, так как при этом устанавливает
ся флаг CF, что изменит pезультат команды ADC. Одним из
решений в данном случае является сохранение флагового
регистра с помощью команды PUSHF, выполнение команды
OR, и, затем, восстановление флагового регистра
командой POPF:

ADC AL,[DI] ;Сложение с переносом
AAA ;Коррекция для ASCII
PUSHF ;Сохранение флагов
OR AL,30H ;Запись левой тройки
POPF ;Восстановление флагов
MOV [BX],AL ;Сохранение суммы

Вместо команд PUSHF и POPF можно использовать команды
LAHF (Load AH with Flags - загрузка флагов в регистр AH) и
SAHF (Store AH in Flag register - запись флагов из регистра
AH во флаговый регистр). Команда LAHF загружает в регистр AH
флаги SF, ZF, AF, PF и CF; а команда SAHF записывает
содержимое регистра AH в указанные флаги. В приведенном
примере, однако, регистр AH уже используется для
арифметических переполнений. Другой способ вставки троек для
получения ASCII-кодов цифр - организовать обработку суммы
командой OR в цикле.

Вычитание в ASCII-формате




Ассемблер для IBM PC. Глава 13 4


Команда AAS (ASCII Adjust for Subtraction - коррекция для
вычитания ASCII-кодов) выполняется aналогично команде AAA.
Команда AAS проверяет правую шест.цифру (четыре бита) в
регистре AL. Если эта цифра лежит между A и F или флаг AF
равен 1, то из регистра AL вычитается 6, а из регистра AH
вычитается 1, флаги AF и CF устанавливаются в 1. Во всех
случаях команда AAS устанавливает в 0 левую шест.цифру в
регистpе AL.
В следующих двух примерах предполагается, что поле ASC1
содержит шест.38, а поле ASC2 - шест.34:

Пример 1: AX AF
MOV AL,ASC1 ;0038
SUB AL,ASC2 ;0034 0
AAS ;0004 0

Пример 2: AX AF
MOV AL,ASC2 ;0034
SUB AL,ASC1 ;00FC 1
AAS ;FF06 1

В примере 1 команде AAS не требуется выполнять коррекцию. В
примере 2, так как правая цифра в регистре AL равна шест.C,
команда AAS вычитает 6 из регистра AL и 1 из регистра AH и
устанавливает в 1 флаги AF и CF. Результат (который должен
быть равен -4) имеет шест. представление FF06, т.е. десятич
ное дополнение числа -4.

Умножение в ASCII-формате

Команда AAM (ASCII Adjust for Multiplication - коррекция
для умножения ASCII кодов) выполняет корректировку
результата умножения ASCII кодов в регистре AX. Однако,
шест. цифры должны быть очищены от троек и полученные данные
уже не будут являться действительными ASCII-кодами. (В
руководствах фирмы IBM для таких данных используется
термин pаспакованный десятичный формат). Например, число в
ASCII-формате 31323334 имеет распакованное десятичное
представление 01020304. Кроме этого, надо помнить, что
коррекция осуществляется только для одного байта за одно
выполнение, поэтому можно умножать только oдно-байтовые
поля; для более длинных полей необходима организация цикла.
Команда AAM делит содержимое регистра AL на 10 (шест. 0A)
и записывает частное в регистр AH, а остаток в AL.
Предположим, что в регистре AL содержится шест. 35, а в
регистре CL - шест.39. Следующие команды умножают содержимое
регистра AL на содержимое CL и преобразуют результат в
ASCII-формат:

AX:
AND CL,0FH ;Преобразовать CL в 09
AND AL,0FH ;Преобразовать AL в 05 0005
MUL CL ;Умножить AL на CL 002D



Ассемблер для IBM PC. Глава 13 5


AAM ;Преобразовать в распак.дес. 0405
OR AX,3030H ;Преобразовать в ASCII-ф-т 3435

Команда MUL генерирует 45 (шест.002D) в регистре AX, после
чего команда AAM делит это значение на 10, записывая частное
04 в регистр AH и остаток 05 в регистр AL. Команда OR преоб
pазует затем распакованное десятичное число в ASCII-формат.
Пример на рис.13.2 демонстрирует умножение четырех-
байтового множимого на одно-байтовый множитель. Так как
команда AAM может иметь дело только с однобайтовыми числами,
то в программе организован цикл, который обрабатывает байты
справа налево. Окончательный результат умножения в данном
примере - 0108090105.
Если множитель больше одного байта, то необходимо
обеспечить еще один цикл, который обрабатывает множитель. В
этом случае проще будет преобразовать число из ASCII-формата
в двоичный формат (см. следующий раздел "Преобразование
ASCII-формата в двоичный формат").

------------------------------------------------------------
------------------------------------------------------------
Рис.13.2. Умножение в ASCII-формате.

Деление в ASCII-формате

Команда AAD (ASCII Adjust for Division - коррекция для
деления ASCII-кодов) выполняет корректировку ASCII кода
делимого до непосредственного деления. Однако, прежде
необходимо очистить левые тройки ASCII-кодов для получения
распакованного десятичного формата. Команда AAD может
оперировать с двухбайтовыми делимыми в регистре AX.
Предположим, что регистр AX содержит делимое 3238 в ASCII-
формате и регистр CL содержит делитель 37 также в ASCII-
формате. Следующие команды выполняют коррекцию для последую
щего деления:
AX:
AND CL,0FH ;Преобразовать CL в распак.дес.
AND AX,0F0FH ;Преобразовать AX в распак.дес. 0208
AAD ;Преобразовать в двоичный 001C
DIV CL ;Разделить на 7 0004

Команда AAD умножает содержимое AH на 10 (шест.0A),
прибавляет pезультат 20 (шест.14) к регистру AL и очищает
регистр AH. Значение 001C есть шест. представление десятич
ного числа 28. Делитель может быть только однобайтовый от 01
до 09.
Пример на рис. 13.3. выполняет деление четырехбайтового
делимого на однобайтовый делитель. В программе организован
цикл обработки делимого справа налево. Остатки от деления
находятся в регистре AH и команда AAD корректирует их в
регистре AL. Окончательный pезультат: частное 00090204 и в
регистре AH остаток 02.




Ассемблер для IBM PC. Глава 13 6


Если делитель больше одного байта, то необходимо постро
ить другой цикл для обработки делителя, но лучше воспользо
ваться следующим разделом "Преобразование ASCII-формата в
двоичный формат."

ДВОИЧНО-ДЕСЯТИЧНЫЙ ФОРМАТ (BCD)
------------------------------------------------------------

В предыдущем примере деления в ASCII-формате было
получено частное 00090204. Если сжать это значение, сохраняя
только правые цифры каждого байта, то получим 0924. Такой
формат называется двоично-десятичным (BCD - Binary Coded
Decimal) (или упакованным). Он содержит только десятичные
цифры от 0 до 9. Длина двоично-десятичного представления в
два раза меньше ASCII-представления.

------------------------------------------------------------
------------------------------------------------------------
Рис.13.3. Деление в ASCII-формате.

Заметим, однако, что десятичное число 0924 имеет основание
10 и, будучи преобразованным в основание 16 (т.е. в шест.
представление), даст шест.039C.
Можно выполнять сложение и вычитание чисел в
двоично-десятичном представлении (BCD-формате). Для этих
целей имеются две корректиpующих команды:

DAA (Decimal Adjustment for Addition -
десятичная коррекция для сложения)
DAS (Decimal Adjustment for Subtraction -
десятичная коррекция для вычитания)