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 ;Округлить оплату
ADC DX,00
CMP DX,SHIFT ;Результат слишком велик
JB F50 ; для команды DIV?
F40:
SUB AX,AX
JMP F70
F50:
CMP ADJUST,00 ;Сдвиг нее требуется?
JZ F80
DIV SHIFT ;Сдвинуть оплату
F70: SUB DX,DX ;Стереть остаток
F80: RET
F10MULT ENDP
; Преобразование в ASCII формат:
; -----------------------------
G10WAGE PROC
LEA SI,ASCWAGE+7 ;Установить дес. точку
MOV BYTE PTR[SI],'.'
ADD SI,NODEC ;Установить правую позицию
G30:
CMP BYTE PTR[SI],'.'
JNE G35 ;Обойти, если дес.поз.
DEC SI
G35:
CMP DX,00 ;Если dx:ax < 10,
JNZ G40
CMP AX,0010 ; то операция завершена
JB G50
G40:
DIV TENWD ;Остаток - ASCII-цифра
OR DL,30H
MOV [SI],DL ;Записать ASCII символ
DEC SI
SUB DX,DX ;Стереть остаток
JMP G30
G50:
OR AL,30H ;Записать последний ASCII
MOV [SI],AL ; символ
RET
G10WAGE ENDP
; Вывод величины оплаты:
; ---------------------
K10DISP PROC
MOV COL,50 ;Установить столбец
CALL Q20CURS
MOV CX,09
LEA SI,ASCWAGE
K20: ;Стереть лидирующие нули
CMP BYTE PTR[SI],30H
JNE K30 ; пробелами
MOV BYTE PTR[SI],20H
INC SI
LOOP K20
K30:
LEA DX,MESSG3 ;Вывод на экран
MOV AH,09
INT 21H
CMP ROW,20 ;Последняя строка экрана?
JAE K80
INC ROW ; нет - увеличить строку
JMP K90
K80:
MOV AX,0601H ; да --
CALL Q10SCR ; прокрутить и
MOV COL,00 ; установить курсор
CALL Q20CURS
K90: RET
K10DISP ENDP
; Преобразование ASCII-чисел
; в двоичное представление:
; --------------------------
M10ASBI PROC
MOV MULT10,0001
MOV BINVAL,00
MOV DECIND,00
SUB BX,BX
M20:
MOV AL,[SI] ;ASCII-символ
CMP AL,'.' ;Обойти, если дес.точка
JNE M40
MOV DECIND,01
JMP M90
M40:
AND AX,000FH
MUL MULT10 ;Умножить на фактор
ADD BINVAL,AX ;Сложить с дв.значением
MOV AX,MULT10 ;Вычислить следующий
MUL TENVD ; фактор x 10
MOV MULT10,AX
CMP DECIND,00 ;Десятичная точка?
JNZ M90
INC BX ; да - обойти точку
M90:
DEC SI
LOOP M20
;Конец цикла
CMP DECIND,00 ;Была дес.точка?
JZ M100 ; да --
ADD NODEC,BX ; сложить с итогом
M100: RET
M10ASBI ENDP
; Прокрутка экрана:
; ----------------
Q10SCR PROC NEAR ;AX установлен при вызове
MOV BH,30 ;Цвет (07 для ч/б)
SUB CX,CX
MOV DX,184FH
INT 10H
RET
Q10SCR ENDP
; Установка курсора:
; -----------------
Q20CURS PROC NEAR
MOV AH,02
SUB BH,BH
MOV DH,ROW
MOV DL,COL
INT 10H
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.13.6. Расчет заработной платы.
О г р а н и ч е н и я. Первое ограничение в программе, приведенной на
рис.13.6, cостоит в том, что допускает не более шести десятичных знаков
после запятой. Другое ограничение - размер самой зарплаты и тот факт, что
сдвиг включает деление на число, кратное 10, a преобразование в
ASCII-формат включает деление на 10. Если значение времени или расценки
содержит больше шести десятичных знаков или зарплата превышает величину
около 655350, то программа выдает нулевой результат. На практике программа
может предусмотреть в данном случае вывод предупреждающего сообщения или
иметь подпрограммы для исключения таких ограничений.
К о н т р о л ь о ш и б о к. Программа, разработанная для
пользователей, не являющихся программистами, должна не только выдавать
предупреждающие сообщения, но также проверять корректность вводимых
значений. Правильными символами при вводе числовых значений являются цифры
от 0 до 9 и символ десятичной запятой. Для любых других символов программа
должна выдать предупреждающее сообщение и вновь повторить запрос на ввод.
Полезной командой для проверки корректности вводимых символов является
XLAT (см. гл.14).
Тщательно проверяйте программы для любых возможных состояний: нулевое
значение, максимально большие и малые значения, отрицательные значения.
Отрицательные величины
------------------------
Некоторые применения программ допускают наличие отрицательных
величин. Знак минус может устанавливаться после числа, например, 12,34-,
или перед числом -12,34. Программа может проверять наличие минуса при
преобразовании в двоичный формат. Можно оставить двоичное число
положительным, но установить соответствующий индикатор исходной
отрицательной величины. После завершения арифметических операций знак
минус при необходимости может быть вставлен в ASCII поле.
Если необходимо, чтобы двоичное число было также отрицательным, то
можно преобразовать, как обычно, ASCII-формат в двоичный, а для изменения
знака двоичного числа воспользоваться командами, описанными в гл.12
"Преобразование знака". Будьте внимательны при использовании команд IMUL и
IDIV для обработки знаковых данных. Для округления отрицательных чисел
следует не прибавлять, а вычитать фактор 5.
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- ASCII-формат требует один байт на каждый символ. Если поле содержит
только цифры от 0 до 9, то замена старших троек в каждом байте на нули
создает распакованный десятичный формат. Сжатие числа до двух цифр в байте
создает упакованный десятичный формат.
- После ASCII-сложения необходимо выполнить коррекцию с помощью
команды AAA; после ASCII-вычитания - коррекция с помощью команды AAS.
- Прежде чем выполнить ASCII-умножение, необходимо преобразовать
множимое и множитель в "распакованный десятичный" формат, обнулив в каждом
байте левые тройки. После умножения необходимо выполнить коррекцию
результата с помощью команды AAM.
- Прежде чем выполнить ASCII-деление, необходимо: 1) преобразовать
делимое и делитель в "распакованный десятичный" формат, обнулив в каждом
байте левые тройки и 2) выполнить коррекцию делимого с помощью команды
AAD.
- Для большинства арифметических операций используйте преобразование
чисел из ASCII-формата в двоичной формат. В процессе такого преобразования
проверяйте на корректность ASCII-символы: они должны быть от шест.30 до
шест.39, могут содержать десятичную запятую (точку) и, возможно, знак
минус.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
13.1. Предположим, что регистр AX содержит 9 в ASCII коде, а регистр
BX -7 также в ASCII коде. Объясните и дайте точный результат для следующих
несвязанных операций:
а) ADD AX,33H б) ADD AX,BX
AAA AAA
в) SUB AX,BX г) SUB AX,0DH
AAS AAS
13.2. Поле UNPAK содержит шест. 01040705 в распаковочном десятичном
формате. Напишите цикл, который преобразует это содержимое в ASCII-формат,
т.е. 31343735.
13.3. Поле ASCA содержит значение 313733 в ASCII-формате, а другое
поле ASCB содержит 35. Напишите команды для умножения этих чисел в
ASCII-формате и записи произведения в поле ASCPRO.
13.4. Используя данные из вопроса 13.3, разделите ASCA на ASCB и
запишите частное в поле ASCQUO.
13.5. Выполните следующие вычисления вручную: а) преобразовать ASCII
46328 в двоичный формат и показать результат в шест.виде; б) преобразовать
полученное шест. значение обратно в ASCII-формат.
13.6. Напишите и выполните программу, которая определяет размер
памяти компьютера (INT 12H - см. гл.2), преобразует полученное значение в
ASCII-формат и выводит результат на экран в следующем виде:
Размер памяти nnn байтов.
ГЛАВА 14 Обработка таблиц
__________________________________________________________________________
Ц е л ь: Раскрыть требования для определения таблиц, организации
поиска в таблицах и сортировки элементов таблицы.
ВВЕДЕНИЕ
________________________________________________________________
Многие программные применения используют табличную организацию таких
данных, как имена, описания, размеры, цены. Определение и использование
таблиц включает одну новую команду ассемблера - XLAT. Таким образом,
использование таблиц - это лишь дело техники и применения знаний,
полученных из предыдущих глав.
Данная глава начинается определением некоторых общепринятых таблиц.
Организация поиска в таблице зависит от способа ее определения. Существует
много различных вариантов определения таблиц и алгоритмов поиска.
ОПРЕДЕЛЕНИЕ ТАБЛИЦ
________________________________________________________________
Для облегчения табличного поиска большинство таблиц определяются
систематично, т.е. элементы таблицы имеют одинаковый формат (символьный
или числовой), одинаковую длину и восходящую или нисходящую
последовательность элементов.
Таблица, которой уже приходилось пользоваться в данной книге - это
стек, представляющий собой таблицу из 64-х неинициализированных слов:
STACK DW 64 DUP(?)
Следующие две таблицы инициализированы символьными и числовыми
значениями:
MONTAB DB 'JAN','FEB','MAR', ... ,'DEC'
COSTAB DB 205,208,209,212,215,224,...
Таблица MONTAB определяет алфавитные аббревиатуры месяцев, а COSTAB -
определяет таблицу номеров служащих. Таблица может также содержать
смешанные данные (регулярно чередующиеся числовые и символьные поля). В
следующей ассортиментной таблице каждый числовой элемент (инвентарный
номер) имеет две цифры (один байт), а каждый символьный элемент
(наименование) имеет девять байтов. Точки, показанные в наименовании
"Paper" дополняют длину этого поля до 9 байт. Точки показывают, что
недостающее пространство должно присутствовать. Вводить точки