Тема: Циклы. Ввод с клавиатуры.
Цель работы: Получение навыков организации циклических структур в ассемблерных программах. Ввод символов с клавиатуры.
Задание: Разработать программу, ввода строковых данных с клавиатуры. В веденной строке удалить пробелы, все строчные символы «а» заменить на прописные «А» и вывести результирующую строку на экран.
Циклы в ассемблерных программах. Организовать циклическую структуру в ассемблерной программе можно двумя способами. Во-первых, используя команды сравнения (CMP) и передачи управления (Jcc), и, во-вторых, используя специальные команды организации циклов (LOOP).
Команда сравнения CMP сравнивает два числа, вычитая второе из первого, также как и команда SUB, но не сохраняя результат. После выполнения команды флаги состояния устанавливаются в соответствии с результатом операции.
Команды перехода можно разделить на две группы: команды условного и безусловного перехода. Безусловный переход – это такой переход, который передает управление без сохранения информации возврата всякий раз, когда выполняется. Ему соответствует команда JMP, имеющая двухбайтное смещение.
|
|
Условный переход проверяет текущее состояние регистра флагов, чтобы определить, передать управление или нет. Все условные переходы имеют однобайтовое смещение. (Более подробно команды условного перехода см. «8. Команды сравнения и передачи управления»)
Ниже приведен фрагмент программы, вычисляющей в цикле сумму цифр от 0 до 9.
MOV AH,0;занести в AH первую цифру «0»
MOV AL,0;подготовить регистр результата
met: ADD AL,AH;прибавить к результату очередную цифру из AH
INC AH;увеличить AH на единицу
CMP AH,10;сравнить значение в AH со значением «10»
JNE met;если AH<>10 то осуществить переход на MET
В приведенном примере в качестве счетчика используется регистр AH и необходимо на каждой итерации цикла самостоятельно производить инкремент счетчика и его сравнение с заданной величиной 10. Для упрощения подобных ситуаций в ассемблере предусмотрены специальные команды для организации циклов. Все команды цикла используют регистр CX в качестве счетчика цикла. Простейшая из них – команда LOOP. Она в конце каждой итерации уменьшает содержимое CX на 1 и передает управление на метку (указанную в команде), если содержимое CX не равно 0. Если вычитание 1 из CX привело к нулевому результату, выполняется следующая команда.
Команда LOOPNE (цикл пока не равно) выходит из цикла, если установлен флаг нуля или если в регистре CX получился 0. Команда LOOPE (цикл пока равно) выполняет обратную к описанной проверку флага нуля: цикл здесь завершается, если регистр CX достиг 0 или если не установлен флаг 0.
|
|
Ниже приведен фрагмент программы, решающий описанную выше задачу, используя команды организации циклов.
MOV AH,0;занести в AH первую цифру «0»
MOV AL,0;подготовить регистр результата
MOV CX,10;количество суммируемых цифр
met: ADD AL,AH;прибавить к результату очередную цифру из AL
LOOP met;если CX<>0 то осуществить переход на MET
Ввод с клавиатуры. Процесс ввода информации в ассемблерных программах осуществляется аналогично выводу:
- в регистр AH заносится номер функции ввода;
- инициируется прерывание, после выполнения которого определенные регистры процессора содержат либо введенную информацию, либо адрес буфера с введенной информацией.
Ниже описан ряд функций прерывания 21h, используемых для ввода информации с клавиатуры.
Функция 01h
Ввод с клавиатуры.
Вход: AH=02h
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и т.п.) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.
Функция 07h
Нефильтруемый консольный ввод без эха.
Вход: AH=07h
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не фильтрует. Не проверяет на Ctrl-Break, backspace и т.п. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Функция 08h
Консольный ввод без эха.
Вход: AH=08h
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23H. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Функция 0ah
Буферизированный ввод строки.
Вход: AH=0ah
DS:DX=адрес входного буфера (смотри ниже)
Выход: буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)
Описание: При входе буфер по адресу DS:DX должен быть оформлен следующим образом:
max | ? | ? | ? | ? | ? | ? | … |
MAX - максимально допустимая длина ввода (от 1 до 254) При выходе буфер заполнен данными следующим образом:
max | len | T | E | X | T | … | 0dh |
LEN - действительная длина данных без завершающего CR (здесь – 0dH).
Символы считываются со стандартного ввода вплоть до CR (ASCII 0dH) или до достижения длины MAX-1. Если достигнут MAX-1, включается консольный звонок для каждого очередного символа, пока не будет введен возврат каретки CR (нажатие Enter). Второй байт буфера заполняется действительной длиной введенной строки, не считая завершающего CR. Последний символ в буфере – всегда CR (который не засчитан в байте длины). Символы в буфере (включая LEN) в момент вызова используются как «шаблон». В процессе ввода действительны обычные клавиши редактирования: Esc выдает "\" и начинает с начала, F3 выдает буфер до конца шаблона, F5 выдает "@" и сохраняет текущую строку как шаблон, и т.д. Большинство расширенных кодов ASCII игнорируются. При распознавании Ctrl-Break выполняется прерывание INT 23H (буфер остается неизменным).
Функция 0ch
Ввод с очисткой
Вход: AH=0ch
AL= номер функции ввода (01H, 06H, 07H, 08H или 0aH)
Выход: нет
Описание: Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа. Следующие значения допустимы в AL: 01H Ввод с клавиатуры; 06H Ввод с консоли; 07H Нефильтрующий без эха; 08H Ввод без эха; 0aH Буферизованный ввод.
Приведенный ниже фрагмент программы иллюстрирует буферизированный ввод строки:
MOV AH,0AH;занесение в AH номера функции
LEA DX,BUF;загрузка DX адресом буфера BUF
INT 21H
...
BUF DB 30,00,30 DUP ('$'),’$’
При организации буфера BUF (размер буфера 30 байт), он весь заполняется символами «$», что удобно, если введенную строку в дальнейшем необходимо выводить на экран или в файл (при условии, конечно, что для ввода буфер будет использоваться лишь однократно).
|
|