Жанр: Учеба
Ассемблер и программирование для IBM PC
...олнение команды 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-формате
---------------------------
Команда AAS (ASCII Adjust for Subtraction - коррекция для вычитания
ASCII-кодов) выполняется аналогично команде AAA. Команда AAS проверяет
правую шест. цифру (четыре бита) в регистре AL. Если эта цифра лежит между
A и F или флаг AF равен 1, то из регистра AL вычитается 6, а из регистра
AH вычитается 1, флаги AF и CF устанавливаются в 1. Во всех случаях
команда AAS устанавливает в 0 левую шест.цифру в регистре 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 для таких данных используется
термин распакованный десятичный формат). Например, число в ASCII-формате
31323334 имеет распакованное десятичное представление 01020304. Кроме
этого, надо помнить, что коррекция осуществляется только для одного байта
за одно выполнение, поэтому можно умножать только одно-байтовые поля; для
более длинных полей необходима организация цикла.
Команда 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
AAM ;Преобразовать в распак.дес. 0405
OR AX,3030H ;Преобразовать в ASCII-ф-т 3435
Команда MUL генерирует 45 (шест.002D) в регистре AX, после чего команда
AAM делит это значение на 10, записывая частное 04 в регистр AH и остаток
05 в регистр AL. Команда OR преобразует затем распакованное десятичное
число в ASCII-формат.
Пример на рис.13.2 демонстрирует умножение четырехбайтового множимого
на однобайтовый множитель. Так как команда AAM может иметь дело только с
однобайтовыми числами, то в программе организован цикл, который
обрабатывает байты справа налево. Окончательный результат умножения в
данном примере - 0108090105.
Если множитель больше одного байта, то необходимо обеспечить еще один
цикл, который обрабатывает множитель. В этом случае проще будет
преобразовать число из ASCII-формата в двоичный формат (см. следующий
раздел "Преобразование ASCII-формата в двоичный формат").
__________________________________________________________________________
TITLE ASCMUL (COM) Умножение ASCII-чисел
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP MAIN
; ---------------------------------------------
MULTCND DB '3783' ;Элементы данных
MULTPLR DB '5'
PRODUCT DB 5 DUP(0)
; ---------------------------------------------
MAIN PROC NEAR
MOV CX,04 ;4 цикла
LEA SI,MULTCND+3
LEA DI,PRODUCT+4
AND MULTPLR,0FH ;Удалить ASCII-тройку
A20:
MOV AL,[SI] ;Загрузить ASCII-символ
; (можно LODSB)
AND AL,OFH ;Удалить ASCII-тройку
MUL MULTPLR ;Умножить
AAM ;Коррекция для ASCII
ADD AL,[DI] ;Сложить с
AAA ; записанным
MOV [DI],AL ; произведением
DEC DI
MOV [DI],AH ;Записать перенос
DEC SI
LOOP A20 ;Циклиться 4 раза
RET
MAIN ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.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), прибавляет результат
20 (шест.14) к регистру AL и очищает регистр AH. Значение 001C есть шест.
представление десятичного числа 28. Делитель может быть только
однобайтовый от 01 до 09.
Пример на рис.13.3 выполняет деление четырехбайтового делимого на
однобайтовый делитель. В программе организован цикл обработки делимого
справа налево. Остатки от деления находятся в регистре AH и команда AAD
корректирует их в регистре AL. Окончательный результат: частное 00090204 и
в регистре AH остаток 02.
Если делитель больше одного байта, то необходимо построить другой
цикл для обработки делителя, но лучше воспользоваться следующим разделом
"Преобразование ASCII-формата в двоичный формат."
__________________________________________________________________________
TITLE ASCDIV (COM) Деление ASCII-чисел
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; ---------------------------------------------
DIVDND DB '3698' ;Элементы данных
DIVSOR DB '4'
QUOTNT DB 4 DUP(0)
; ---------------------------------------------
MAIN PROC NEAR
MOV CX,04 ;4 цикла
SUB AH,AH ;Стереть левый байт делимого
AND DIVSOR,0FH ;Стереть ASCII 3 в делителе
LEA SI,DIVDND
LEA DI,QUOTNT
A20:
MOV AL,[SI] ;Загрузить ASCII байт
; (можно LODSB)
AND AL,0FH ;Стереть ASCII тройку
AAD ;Коррекция для деления
DIV DIVSOR ;Деление
MOV [DI],AL ;Сохранить частное
INC SI
INC DI
LOOP A20 ;Циклиться 4 раза
RET
MAIN ENDP
CODEGS ENDS
END BEGIN
__________________________________________________________________________
Рис.13.3. Деление в ASCII-формате.
ДВОИЧНО-ДЕСЯТИЧНЫЙ ФОРМАТ (BCD)
________________________________________________________________
В предыдущем примере деления в ASCII-формате было получено частное
00090204. Если сжать это значение, сохраняя только правые цифры каждого
байта, то получим 0924. Такой формат называется двоично-десятичным (BCD -
Binary Coded Decimal) (или упакованным). Он содержит только десятичные
цифры от 0 до 9. Длина двоично-десятичного представления в два раза меньше
ASCII-представления.
Заметим, однако, что десятичное число 0924 имеет основание 10 и,
будучи преобразованным в основание 16 (т.е. в шест. представление), даст
шест.039C.
Можно выполнять сложение и вычитание чисел в двоично-десятичном
представлении (BCD-формате). Для этих целей имеются две корректирующих
команды:
DAA (Decimal Adjustment for Addition - десятичная коррекция для сложения)
DAS (Decimal Adjustment for Subtraction - десятичн. коррекция для вычит.)
Обработка полей также осуществляется по одному байту за одно
выполнение. В примере программы, приведенном на рис.13.4, выполняется
преобразование чисел из ASCII-формата в BCD-формат и сложение их.
Процедура B10CONV преобразует ASCII в BCD. Обработка чисел может
выполняться как справа налево, так и слева направо. Кроме того, обработка
слов проще, чем обработка байтов, так как для генерации одного байта
BCD-кода требуется два байта ASCII-кода. Ориентация на обработку слов
требует четного количества байтов в ASCII-поле.
Процедура C10ADD выполняет сложение чисел в BCD-формате.
Окончательный результат - 127263.
__________________________________________________________________________
TITLE BCDADD (СОМ) Преобр.ASCII в BCD, сложение
CODESG SEGMENT PARA "Code"
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; -------------------------------------------
ASC1 DB '057836'
ASC2 DB '069427'
BCD1 DB '000'
BCD2 DB '000'
BCD3 DB 4 DUP(0)
; -------------------------------------------
MAIN PROC NEAR
LEA SI,ASC1+4 ;Инициализировать для ASC1
LEA DI,BCD1+2
CALL B10CONV ;Вызвать преобразование
LEA SI,ASC2+4 ;Инициализировать для ASC2
LEA DI,BCD2+2
CALL B10CONV ;Вызвать преобразование
CALL C10ADD ;Вызвать сложение
RET
MAIN ENDP
; Преобразование ASCII в BCD:
; --------------------------
B10CONV PROC
MOV CL,04 ;Фактор сдвига
MOV OX,03 ;Число слов В20:
MOV AX,[SI] ;Получить ASCII-пару
(можно использовать LODSW)
XCHG AH,AL
SHL AL,CL ;Удалить тройки
SHL AX,CL ; ASCII-кода
MOV [DI],AH ;Записать BCD-цифру
DEC SI
DEC SI
DEC DI
DEC DX
JNZ В20
RET
B10CONV ENDP
; Сложение BCD-чисел:
; ------------------
C10ADD PROC
XOR АН,АН ;0чистить АН
LEA SI,BCD1+2 ;Инициализация
LEA DI,BCD2+2 ; BCD
LEA BX,BCD3+3 ; адресов
MOV CX,03 ;Трехбайтные поля
CLC
С20:
MOV AL,[SI] ;Получить BCD1 (или LODSB)
ADC AL,[DI] ;Прибавить BCD2
DAA ;Десятичная коррекция
MOV [BX],AL ;3аписать в BCD3
DEC SI
DEC DI
DEC BX
LOOP С20 ;Цикл 3 раза
RET
C10ADD ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.13.4. BCD-преобразование и арифметика.
ПРЕОБРАЗОВАНИЕ ASCII-ФОРМАТА В ДВОИЧНЫЙ ФОРМАТ
________________________________________________________________
Выполнение арифметических операций над числами в ASCII или BCD
форматах удобно лишь для коротких полей. В большинстве случаев для
арифметических операций используется преобразование в двоичный формат.
Практически проще преобразование из ASCII-формата непосредственно в
двоичный формат, чем преобразование из ASCII- в BCD-формат и, затем, в
двоичный формат:
Метод преобразования базируется на том, что ASCII-формат имеет
основание 10, а компьютер выполняет арифметические операции только над
числами с основанием 2. Процедура преобразования заключается в следующем:
1. Начинают с самого правого байта числа в ASCII-формате и
обрабатывают справа налево.
2. Удаляют тройки из левых шест.цифр каждого ASCII-байта.
3. Умножают ASCII-цифры на 1, 10, 100 (шест.1, A, 64) и т.д. и
складывают результаты.
Для примера рассмотрим преобразование числа 1234 из ASCII-формата в
двоичный формат:
Десятичное Шестнадцатиричное
4 х 1 = 4 4
3 х 10 = 30 1E
2 х 100 = 200 C8
1 х 1000 = 1000 3E8
Результат: 04D2
Проверьте, что шест.04D2 действительно соответствует десятичному
1234. На рис.13.5 в процедуре B10ASBI выполняется преобразование
ASCII-числа 1234 в двоичный формат. В примере предполагается, что длина
ASCII-числа равна 4 и она записана в поле ASCLEN. Для инициализации адрес
ASCII-поля ASCVAL-1 заносится в регистр SI, а длина - в регистр BX.
Команда по метке B20 пересылает ASCII-байт в регистр AL:
MOV AL,[SI+BX]
Здесь используется адрес ASCVAL-1 плюс содержимое регистра BX (4),
т.е. получается адрес ASCVAL+3 (самый правый байт поля ASCVAL). В каждом
цикле содержимое регистра BX уменьшается на 1, что приводит к обращению к
следующему слева байту. Для данной адресации можно использовать регистр
BX, но не CX, и, следовательно, нельзя применять команду LOOP. В каждом
цикле происходит также умножение поля MULT10 на 10, что дает в результате
множители 1,10,100 и т.д. Такой прием применен для большей ясности,
однако, для большей производительности множитель можно хранить в регистре
SI или DI.
__________________________________________________________________________
TITLE EXCONV (СОМ) Преобр. ASCII и дв. ф-тов
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; -------------------------------------------
ASCVAL DB '1234' ;Элементы данных
BINVAL DB 0
ASCLEN DB 4
MULT10 DB 1
; -------------------------------------------
MAIN PROC NEAR ;Основная процедура:
CALL B10ASBI ;Вызвать преобразование ASCII
CALL C10BIAS ;Вызвать преобразование двоичное
RET
MAIN ENDP
; -------------------------------
; Преобразование ASCII в двоичное:
; -------------------------------
B10ASBI PROC
МОV CX,10 ;Фактор умножения
LEA SI,ASCVAL-1 ;Адрес ASCVAL
MOV BX,ASCLEN ;Длина ASCVAL
В20:
MOV AL,[SI+BX] ;Выбрать ASCII-символ
AND AX,000FH ;Очистить зону тройки
MUL MULT10 ;Умножить на фактор 10
ADD BINVAL,AX ;Прибавить к двоичному
MOV AX,MULT10 ;Вычислить следующий
MUL CX ; фактор умножения
MOV MULT10,AX
DEC BX ;Последн. ASCII-символ?
JNZ В20 ; Нет - продолжить
RET
B10ASBI ENDP
; -------------------
; Преобр. дв. в ASCII:
; -------------------
C10BIAS PROC
MOV CX,0010 ;Фактор деления
LEA SI,ASCVAL+3 ;Адрес ASCVAL
MOV AX,BINVAL ;Загрузить дв. число
С20:
CMP АХ,0010 ;Значение меньше 10?
JB С30 ; Да - выйти
XOR DX,DX ;Очистить часть частного
DIV CX ;Разделить на 10
OR DL,30H
MOV [SI],DL ;Записать ASCII-символ
OEC SI
JMP С20
C30:
OR AL,30H ;3аписать посл. частное
MOV [SI],AL ; как ASCII-символ
RET
C10BIAS ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.13.5. Преобразование ASCII и двоичного форматов.
ПРЕОБРАЗОВАНИЕ ДВОИЧНОГО ФОРМАТА В ASCII-ФОРМАТ
________________________________________________________________
Для того, чтобы напечатать или отобразить на экране арифметический
результат, необходимо преобразовать его в ASCII-формат. Данная операция
включает в себя процесс обратный предыдущему. Вместо умножения
используется деление двоичного числа на 10 (шест.0A) пока результат не
будет меньше 10. Остатки, которые лежат в границах от 0 до 9, образуют
число в ASCII-формате. В качестве примера рассмотрим преобразование
шест.4D2 обратно в десятичный формат:
Частное Остаток
4D2 : A 7B 4
7B : A C 3
C : A 1 2
Так как последнее частное 1 меньше, чем шест.A, то операция завершена.
Остатки вместе с последним частным образуют результат в ASCII-формате,
записываемый справа налево 1234. Все остатки и последнее частное должны
записываться в память с тройками, т.е. 31323334.
На рис.13.5 процедура C10BIAS преобразует шест.4D2 (результат
вычисления в процедуре B10ASBI) в ASCII-число 1234. Полезно переписать всю
программу (рис.13.5) в компьютер и выполнить трассировку ее выполнения по
шагам.
СДВИГ И ОКРУГЛЕНИЕ
________________________________________________________________
Рассмотрим процесс округления числа до двух десятичных знаков после
запятой. Если число равно 12,345, то необходимо прибавить 5 к
отбрасываемому разряду и сдвинуть число вправо на один десятичный разряд:
Число: 12,345
Плюс 5: +5
------
Округленное число: 12,350 = 12,35
Если округляемое число равно 12,3455, то необходимо прибавить 50 и
сдвинуть на два десятичных разряда. Для 12,34555 необходимо прибавить 500
и сдвинуть на три десятичных разряда:
12,3455 12,34555
+50 +500
------- --------
12,3505 = 12,35 12,35055 = 12,35
К числу, имеющему шесть знаков после запятой, необходимо прибавить 5000 и
сдвинуть на четыре десятичных разряда и т.д. Поскольку данные
представляются в компьютере в двоичном виде, то 12345 выглядит как
шест.3039. Прибавляя 5 к 3039, получим 303E, что соответствует числу 12350
в десятичном представлении. Пока все хорошо. Но вот сдвиг на одну двоичную
цифру дает в результате шест.181F, или 1675 - т.е. сдвиг на одну двоичную
цифру просто делит число пополам. Но нам необходим такой сдвиг, который
эквивалентен сдвигу вправо на одну десятичную цифру. Такой сдвиг можно
осуществить делением на 10 (шест.A):
Шест.303E : Шест.A = 4D3 или дес.1235
Преобразование шест.4D3 в ASCII-формат дает число 1235. Теперь остается
лишь вставить запятую в правильную позицию числа 12,35, и можно выдать на
экран округленное и сдвинутое значение.
Таким образом можно округлять и сдвигать любые двоичные числа. Для
трех знаков после запятой необходимо прибавить 5 и разделить на 10, для
четырех знаков после запятой: прибавить 50 и разделить на 100. Возможно вы
заметили модель: фактор округления (5, 50, 500 и т.д.) всегда составляет
половину фактора сдвига (10, 100, 1000 и т.д.).
Конечно, десятичная запятая в двоичном числе только подразумевается.
ПРОГРАММА: ПРЕОБРАЗОВАНИЕ ВРЕМЕНИ И РАСЦЕНКИ РАБОТ ДЛЯ РАСЧЕТА ЗАРПЛАТЫ
_______________________________________________________________________
Программа, приведенная на рис.13.6, позволяет вводить с клавиатуры
значения продолжительности и расценки работ и отображать на экран
расчитанную величину заработанной платы. Для краткости в программе опущены
некоторые проверки на ошибку. Программа содержит следующие процедуры:
B10INPT Вводит значения времени работы на ее расценку с клавиатуры. Эти
значения могут содержать десятичную запятую.
D10HOUR Выполняет преобразование значения времени из ASCII в двоичный
формат.
E10RATE Выполняет преобразование значения расценки из ASCII в двоичный
формат.
F10MULT Выполняет умножение, округление и сдвиг. Величина зарплаты без
дробной части или с одним или двумя знаками после запятой не
требует округления и сдвига. Данная процедура ограничена тем,
что позволяет обрабатывать величину зарплаты с точностью до
шести десятичных знаков, что, конечно, больше, чем требуется.
G10WAGE Вставляет десятичную запятую, определяет правую позицию для
начала записи ASCII символов и преобразует двоичное значение
зарплаты в ASCII-формат.
K10DISP Заменяет лидирующие нули на пробелы и выводит результат на экран
M10ASBI Преобразует ASCII в двоичный формат (общая процедура для времени
и расценки) и определяет число цифр после запятой в введенном
значении.
__________________________________________________________________________
TITLE SCREMP (EXE) Ввод времени и расценки,
;вывод величины оплаты
; ----------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
DW 32 DUP(?)
STACKSG ENDS
; ----------------------------------------------------
DATASG SEGMENT PARA 'Data'
HRSPAR LABLE BYTE ;Список параметров для
; ввода времени:
MAXHLEN DB 6 ;---------------------
ACTHLEN DB ?
HRSFLD DB 6 DUP(?)
RATEPAR LABLE BYTE ;Список параметров для
; ввода расценки:
MAXRLEN DB 6 ;---------------------
ACTRLEN DB ?
RATEFLN DB 6 DUP(?)
MESSG1 DB 'Hours worked? ','$'
MESSG2 DB 'Rate of pay? ','$'
MESSG3 DB 'Wage = '
ASCWAGE DB 10 DUP(30H), 13, 10, '$'
ADJUST DW ?
ASCHRS DB 0
ASCRATE DB 0
BINVAL DW 00
BINHRS DW 00
BINRATE DW 00
COL DB 00
DECIND DB 00
MULT10 DW 01
NODEC DW 00
ROW DB 00
SHIFT DW ?
TENWD DW 10
DATASG ENDS
; ----------------------------------------------------
CODESG SEGMENT PARA 'Code'
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATASG
MOV DS,AX
MOV ES,AX
MOV AX,0600H
CALL Q10SCR ;Очистить экран
CALL Q20CURS ;Установить курсор
A20LOOP:
CALL B10INPT ;Ввести время и расценку
CMP ACTHLEN,00 ;Завершить работу?
JE A30
CALL D10HOUR ;Получить двоичное время
CALL E10RATE ;Получить двоичную расценку
CALL F10MULT ;Расчитать оплату
CALL G10WAGE ;Преобразовать в ASCII
CALL K10DISP ;Выдать результат на экран
JMP A20LOOP
A30:
MOV AX,0600H
CALL Q10SCR ;Очистить экран
RET ;Выйти из программы
BEGIN ENDP
; Ввод времени и расценки
; ----------------------------------------------------
B10INPT PROC
LEA DX,MESSG1 ;Запрос для ввода времени
MOV AH,09
INT 21H
LEA DX,HRSPAR ;Ввести время
MOV AH,0AH
INT 21H
CMP ACTHLEN,00 ;Пустой ввод?
JNE B20
RET ; да - вернуться A20LOOP
B20:
MOV COL,25 ;Установить столбец
CALL Q20CURS
LEA DX,MESSG2 ;Запрос для ввода расценки
MOV AH,09
INT 21H
LEA DX,RATEPAR ;Ввести расценку
MOV AH,0AH
INT 21H
RET
B10INPT ENDP
; Обработка времени:
; -----------------
D10HOUR PROC
MOV NODEC,00
MOV CL,ACTHLEN
SUB CH,CH
LEA SI,HRSFLD-1 ;Установить правую позицию
ADD SI,CX ; времени
CALL M10ASBI ;Преобразовать в двоичное
MOV AX,BINVAL
MOV BINHRS,AX
RET
D10HOUR ENDP
; Обработка расценки:
; ------------------
E10RATE PROC
MOV CL,ACTRLEN
SUB CH,CH
LEA SI,RATEFLD-1 ;Установить правую позицию
ADD SI.CX ; расценки
CALL M10ASBI ;Преобразовать в двоичное
MOV AX,BINVAL
MOV BINRATE,AX
RET
E10RATE ENDP
; Умножение, округление и сдвиг:
; -----------------------------
F10MULT PROC
MOV CX,05
LEA DI,ASCWAGE ;Установить формат оплаты
MOV AX,3030H ; в код ASCII (30)
CLD
REP STOSW
MOV SHIFT,10
MOV ADJUST,00
MOV CX,NODEC
CMP CL,06 ;Если более 6 десятичных
JA F40 ; знаков, то ошибка
DEC CX
DEC CX
JLE F30 ;Обойти, если менее 3 знаков
MOV NODEC,02
MOV AX,01
F20:
MUL TENWD ;Вычислить фактор сдвига
LOOP F20
MOV SHIFT,AX
SHR AX,1 ;Округлить результат
MOV ADJUST,AX
F30:
MOV AX,BINHRS
MUL BINRATE ;Вычислить оплату
ADD AX,ADJUST ;Округлить опла
...Поділитися у соцмережах