Фильтр
Калькулятор
Усовершенствованный калькулятор
Резюме
В предыдущей теме была рассмотрена программа для ввода шестнадцатеричных чисел. Но эта программа обладала существенным недостатком: кроме чисел 0 ... F она воспринимала практически все вводимые символы, и интерпретировала их как числа.
Поэтому, нам следует написать процедуру, которая при вводе будет фильтровать символы шестнадцатеричных чисел: "0" ... "9", "A" ... "F".
Фильтр
Рассмотрим две новые инструкции, которые потребуются для фильтрации чисел:
JA ("Jump if Above" - перейти если больше) JB ("Jump if Below" - перейти если меньше)
Инструкции JA и JB работают только с положительными числами 0 ... FFFFh, и игнорируют флаг переполнения (OF). Изученная ранее инструкция JL (перейти, если меньше), работает как с положительными, так и отрицательными числами (проверяет OF).
Если для запроса символа использовать функцию 01h прерывания INT 21h, то ввод любого символа будет сопровождаться эхом (т.е. выводом данного символа на экран).
Новая процедура не должна отображать ошибочно введенные символы. Для ввода символа без эхо-повтора, мы используем функцию 08h прерывания INT 21h.
Ниже приводится программа-тест для проверки фильтра. Для повышения читабельности, из листинга удалены коды инструкций и сегмент адреса. Инструкции основной программы внесите по адресам 100h и 103h, а процедуру расположите по адресу 200h:
0100 CALL 0200 основная программа
0103 INT 20
0200 PUSH DX процедура ввода и фильтрации чисел 0 ... F
0201 MOV AH,08 ввод символа без эха
0203 INT 21
0205 CMP AL,30
0207 JB 0203 если AL < 30h, то переход на 203h
0209 CMP AL,46
020B JA 0203 если AL > 46h, то переход на 203h
020D CMP AL,3A
020F JB 0215 если AL < 3Ah, то переход на 215h
0211 CMP AL,41
0213 JB 0203 если AL < 41h, то переход на 203h
0215 MOV AH,02
0217 MOV DL,AL печать отфильтрованного символа
0219 INT 21
021B SUB AL,30
021D CMP AL,09 преобразование кода символа в число
021F JLE 0223
0221 SUB AL,07
0223 POP DX
0224 RET
Протестируйте программу с различными символами и убедитесь, что фильтр пропускает только символы шестнадцатеричных чисел: "0" ... "F". Проверьте ввод символов "a" ... "f".
Почему процедура начинается с адреса 200h? Процедуры могут располагаться в любом месте программы, но обычно их пишут после основной программы. Адрес 200h выбран с учетом места под текст основной программы (100h - ячеек). Можно перенести процедуру на адрес 105h, тогда между основной программой и процедурой не останется свободных ячеек. При этом придется поменять все адреса в инструкциях условных переходов.
В процедуре используются регистры AX и DX, но в стеке сохраняется только регистр DX. Почему? В ходе выполнения процедуры, в AL передается цифра введенная с клавиатуры. Если в начале процедуры сохранить значение регистра AX в стек, а в конце процедуры его восстановить, то введенная внутри процедуры цифра будет потеряна. Поэтому, не каждый регистр можно временно сохранять в стеке.
Данную процедуру можно использовать для ввода двузначных чисел. Например, программа должна запрашивать hex-код символа, и выводить этот символ на экран:
0100 CALL 0200 переход на процедуру ввода hex-цифры
0103 MOV DL,AL
0105 MOV CL,04
0107 SHL DL,CL
0109 CALL 0200 переход на процедуру ввода hex-цифры
010C ADD DL,AL
010E MOV AH,02
0110 INT 21
0112 INT 20
Проверьте работу программы с кодами: 2Ah (символ "*"), 07h (звуковой сигнал), 40h (символ "@") и др.
Калькулятор
Программа запрашивает две hex-цифры, суммирует их и выводит результат на экран. Например: F + 1 = 10
0100 CALL 0200
0103 MOV BL,AL
0105 MOV AH,02
0107 MOV DL,2B печать знака "+"
0109 INT 21
010B CALL 0200
0110 MOV AH,02
0112 MOV DL,3D печать знака "="
0114 INT 21
010E ADD BL,AL
0116 CALL 0150
0119 INT 20
...
0150 Процедура печати двузначного числа из регистра BL
...
0200 Процедура ввода hex-цифры в регистр AL
Программу печати двузначного числа из регистра BL нужно переделать в процедуру:
- замените INT 20h на RET;
- измените адреса в инструкциях JL;
- можете добавить инструкции PUSH и POP (но в данном случае это не обязательно).
Задачи:
- Если результат сложения меньше 10h, то в старшем разряде ответа печатается ноль. Например: 3 + 2 = 05. Вам нужно убрать этот "лишний" ноль.
- Убрать пустые адресные пространства между основной программой и процедурами. Записать программу на диск.
Усовершенствованный калькулятор
Вы написали программу, которая умеет складывать два шестнадцатеричных числа. Теперь необходимо "обучить" калькулятор вычитанию.
В приложениях находится текст готовой программы. Но не спешите искать готовое решение. Эта программа является итоговой задачей, желательно написать ее самостоятельно. Если вы успешно справитесь с ней, то знайте: время, проведенное за клавиатурой, потрачено не зря.
Для написания программы можно использовать следующую блок-схему:
Ввод-фильтр первой цифры, копия числа в регистре BH. |
Ввод-фильтр знака "+" или "-", копия знака в регистре DH. |
Ввод-фильтр второй цифры, копия числа в регистре BL. |
Ввод-фильтр знака "=". После ввода "=" появляется ответ. |
Вычисление результата: если DH = "+", то BH + BL если DH = "-", то BH - BL |
Вывод результата на экран. |
INT 20h |
Процедура: "Вывод символа на экран" |
Процедура: "Ввод-фильтр hex-цифры" |
Эта блок-схема не является единственным решением, вы можете разработать свой вариант алгоритма.
Программу можно подготовить в более простом виде: без контроля отрицательных чисел и проверки разрядности числа. Например:
1 - 2 = FF 2 + 3 = 05
В усложненном варианте результат выглядит иначе:
1 - 2 = -1 2 + 3 = 5
Именно так формирует результат программа из приложения.
Для написания программы вам может потребоваться инструкция безусловного перехода: JMP (Jump - переход). Например:
JMP 210 переход на адрес 210h
Резюме
Седьмая тема завершает вводную часть курса "Основы программирования на ассемблере". Теперь вы знаете, что:
- числа можно представлять не только в десятичной системе счисления;
- арифметические операции выполняются в любой системе счисления;
- регистры позволяют хранить в микропроцессоре одновременно несколько чисел;
- система команд CPU позволяет выполнять арифметические и другие действия;
- процедуры и прерывания значительно упрощают разработку программ.
Многое из того, что вы написали, будет использовано далее. Во второй части курса мы перейдем к более серьезным и интересным вопросам программирования на ассемблере.
|