Лабораторная работа №3
Тема: Циклы. Ввод с клавиатуры.
Цель работы: Получение навыков организации циклических структур в ассемблерных программах. Ввод символов с клавиатуры.
Задание: Разработать программу, ввода строковых данных с клавиатуры. В веденной строке удалить пробелы, все строчные символы «а» заменить на прописные «А» и вывести результирующую строку на экран.
Циклы в ассемблерных программах. Организовать циклическую структуру в ассемблерной программе можно двумя способами. Во-первых, используя команды сравнения (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, используемых для ввода информации с клавиатуры.
Ввод с клавиатуры.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и т.п.) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.
Нефильтруемый консольный ввод без эха.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не фильтрует. Не проверяет на Ctrl-Break, backspace и т.п. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Консольный ввод без эха.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23H. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Буферизированный ввод строки.
DS:DX=адрес входного буфера (смотри ниже)
Выход: буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)
Описание: При входе буфер по адресу DS:DX должен быть оформлен следующим образом:
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 (буфер остается неизменным).
Ввод с очисткой
AL= номер функции ввода (01H, 06H, 07H, 08H или 0aH)
Описание: Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа. Следующие значения допустимы в AL: 01H Ввод с клавиатуры; 06H Ввод с консоли; 07H Нефильтрующий без эха; 08H Ввод без эха; 0aH Буферизованный ввод.
Приведенный ниже фрагмент программы иллюстрирует буферизированный ввод строки:
MOV AH,0AH ;занесение в AH номера функции
LEA DX,BUF ;загрузка DX адресом буфера BUF
BUF DB 30,00,30 DUP (‘$’),’$’
При организации буфера BUF (размер буфера 30 байт), он весь заполняется символами «$», что удобно, если введенную строку в дальнейшем необходимо выводить на экран или в файл (при условии, конечно, что для ввода буфер будет использоваться лишь однократно).
Не нашли то, что искали? Воспользуйтесь поиском:
Лучшие изречения: Студент — человек, постоянно откладывающий неизбежность. 10529 — | 7318 — или читать все.
188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.
Отключите adBlock!
и обновите страницу (F5)
очень нужно
«Assembler IBM PC 7. Лабораторная работа № 2. Системные функции dos ввода-вывода информации. Обработка строковых переменных»
7.1. ЦЕЛЕВЫЕ УСТАНОВКИ
· Освоение стандартных способов ввода-вывода DOS.
· Разработка программ по обработке символьной информации с использованием строковых команд.
7.2. МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ
7.2.1. ВЫЗОВЫ ФУНКЦИЙ MS-DOS ДЛЯ ВВОДА-ВЫВОДА СИМВОЛЬНОЙ ИНФОРМАЦИИ
Для того чтобы написать простую, но законченную программу, необходимо знать три вещи – как вводить данные, как выводить результат и как остановить выполнение программы. В языках высокого уровня имеются специальные операторы ввода/вывода, которые позволяют в удобной форме реализовать эти функции. В системе команд процессора ix86 также имеются команды ввода/вывода, но они реализуют эти операции на самом низком, физическом уровне, т.е. обеспечивают обращение к портам ввода/вывода по конкретным адресам. Для обеспечения ввода/вывода информации на этом уровне программист должен знать номера портов каждого устройства, а также протоколы или алгоритмы обслуживания этих устройств. Операционная система MS DOS реализует ряд сервисных функций ввода/вывода на логическом уровне, которые выступают как пронумерованные функции прерывания Int 21h. При этом прикладная программа пользователя должна сообщить необходимые для данной функции параметры и передать управление DOS, которая и осуществит все необходимые операции по управлению устройством на физическом уровне (где-то, возможно, обратится за помощью к BIOS), а затем вернёт управление прикладной задаче, сообщив, успешно ли завершилась операция или же была допущена ошибка.
Прерывания, в основном, можно разделить на два основных типа: аппаратные (hardware) и программные (software interrupt). Аппаратные прерывания вызываются сигналами от периферийных устройств, требующими обслуживания процессором, а программные, через посредство команды Int, вызывающей какую-либо сервисую функцию (процедуру) DOS или BIOS. Перечень функций, выполняемых операционной системой DOS, подробно изложен в п. 3.
Упрощенная схема обработки прерывания изображена на рис. 2.1. Процессор выполняет команду прерывания, используя таблицу векторов, где содержатся все адресные указатели обработчиков (аппаратных и программных) прерываний. Действия процессора при переходе на выполнение подпрограммы-обработчика (инициируемое командой Int n) и последующем возврате обратно (при встрече команды Iret) в точку выхода из основной программы показаны на рис. 2.1 цифрами в кружках. Одно и то же прерывание может выполнять несколько различных функций, код которых помещается в регистрah, а дополнительные параметры заносятся в другие регистры РОН. Возвращаемая обработчиком информация содержится в регистре al или ax, если флаг cf=0. Флаг cf устанавливается в 1, если произошла какая-либо ошибка, код которой заносится в регистр ax (так называемый код возврата ошибки). Возможные коды ошибок приводятся в руководствах по DOS [4, 10, 12].
Рис. 2.1. Упрощенная схема обработки программного прерывания Int n
Функции информационного обмена MS DOS в своём развитии изменялись от специализированных программ обмена для каждого типа устройства на основе блока управления файлами FCB (File ControlBlock) до унификации обмена на основе файловой системы через дескрипторы. Дескриптор или логический номер файла идентифицирует файл или устройство, с которым должна работать прикладная программа. Это упрощает программирование операций ввода/вывода, т.к. позволяет осуществлять обмен информации независимо от природы файла (устройства). Существует пять стандартных дескрипторов файлов, которые предоставляются прикладной программе:
· – стандартный ввод с консоли (обычно клавиатура);
· 1 – стандартный вывод на консоль (обычно экран дисплея);
· 2 – устройство вывода ошибок (всегда дисплей);
· 3 – внешнее устройство обмена AUX (асинхронный адаптер COM1);
· 4 – стандартный принтер (первый параллельный порт LPT1).
Стандартный ввод (как и стандартный вывод) можно перенаправить средствами DOS на любое устройство или в файл, а стандартная ошибка всегда связана с экраном (обычно дескриптор 2 используют для вывода диагностических сообщений). Перенаправление ввода или вывода программы осуществляет командный процессор Command.com. Если, допустим, в программе prog предусмотрен ввод данных через дескриптор стандартного ввода ²0², а вывод данных через дескриптор вывода ²1², то при обычном запуске программы командой prog.exe программа будет требовать входные данные с клавиатуры и выводить результаты своей работы на экран. Если, однако, при запуске программы использовать символ перенаправления
то система сама создаст файл file.txt, и весь вывод программы будет записан в этот файл. Ввод по-прежнему будет осуществляться с клавиатуры. Запуск программы командой
заставит программу выполняться в режиме ввода информации из файла file.dat и вывода в файл file.txt. Ни экран, ни клавиатура использоваться не будут. Сама программа ничего не знает об этих перенаправлениях – она во всех случаях обращается к стандартному устройству ввода данных и к стандартному устройству вывода данных. Просто DOS как бы подставляет ей на входе и выходе другие устройства.
7.2.2. ВВОД С КЛАВИАТУРЫ СИМВОЛЬНОЙ ИНФОРМАЦИИ
7.2.2.1. Буфер ввода данных с клавиатуры
Нажатие любой клавиши клавиатуры вызывает сигнал аппаратного прерывания (прерывания с типом 09h), заставляющий процессор прервать исполняемую программу и перейти на подпрограмму обработки прерывания от клавиатуры. Обработчик прерывания формирует двухбайтовый код с последующей засылкой его в кольцевой буфер ввода данных с клавиатуры, располагающийся по адресу 0040h:001Eh в системной области оперативной памяти. Для алфавитно-цифровых клавиш старший байт этого кода представляет scan-код клавиши (условный номер клавиши на клавиатуре), а младший – ASCII-код клавиши, т.е. 8-битовый код закреплённого за этой клавишей символа.
Заполнение буфера клавиатуры, рассчитанного на 15 слов или ударов по клавишам, происходит по мере нажатия клавиш и не связано с выполнением текущей программы. Если программе требуется ввести с клавиатуры определённый символ (или строку), она с помощью соответствующей системной функции DOS обращается к буферу ввода и, при наличии в нём данных, передаёт первый из поступивших в этот буфер символов в программу. Дело в том, что запись и считывание кодовых слов в буфер клавиатуры соответствует принципу FIFO (first in – first out, первым вошёл – первым вышел), поэтому считывание символа из буфера освобождает место для ввода последующих. Если к моменту вызова функции DOS буфер ввода оказывается пуст, DOS будет непрерывно опрашивать его состояние, ожидая появления в буфере очередного кода, а исполнение программы приостанавливается до нажатия клавиши.
7.2.2.2. Системные функции DOS ввода данных с клавиатуры
DOS предоставляет несколько способов ввода данных с клавиатуры [4, 5, 7, 11, 12, 13, 14]:
¨ использование группы функций Int 21h (01h, 06h, 07h, 08h, 0Ah¸0Ch), обеспечивающих посимвольный ввод с клавиатуры в разных режимах;
¨ обращение к клавиатуре, как к файлу, с помощью функции 3Fh.
Функции DOS, осуществляющие ввод с клавиатуры, различаются друг от друга некоторыми другими важными характеристиками, которые приведены в табл. 2.1.
Сравнительная характеристика функций DOS ввода с клавиатуры
Номер функции DOS →
01h
06h
07h
08h
0Ah
0Bh
Ch
Реакция на Ctrl+C
Ожидание нажатия клавиши
Ввод расширенных кодов ASCII
Ввод кодов с помощью Alt/цифра
– Эхо-символы. Отображение вводимого символа на экране.
– Реакция на Ctrl+C. Аварийное завершение программы (ASCII-код 03h). Вызывается обработчик прерывания Int 23h, завершающий текущую программу с выходом в DOS.
– Ожидание нажатия клавиши. Функция, при отсутствии символа в кольцевом буфере ожидает его ввода. Функции, обладающие этим свойством, являются синхронными, иначе – асинхронными.
– Ввод расширенных кодов ASCII. Все функции DOS, считывающие данные с клавиатуры, передают в программу только ASCII-код (младший байт кодового слова клавиши), оставляя scan-код (старший байт) без внимания. Правда, это относится только к алфавитно-цифровым клавишам, т. е. клавишам, за которыми закреплены отображаемые на экране символы (94 символа со значениями ASCII-кода от 32 до 126). Особенности считывания информационных кодов с других, так называемых функциональных и управляющих клавиш, будут рассмотрены дальше в разделе ²Расширенные коды ASCII².
– Очистка буфера. Процесс считывания кодов с буфера ввода может дать непредсказуемый эффект, если перед вызовом функции DOS этот буфер не был пуст. Программа, не желающая вводить набранные досрочно коды, должна очистить клавиатурный буфер с помощью специальной функции Ch прерывания 21h (при al = 0).
– Ввод кодов с помощью комбинации Alt/цифра. Позволяет вводить в программу коды символов второй половины ASCII-таблицы, с использованием цифровой клавиатуры (правая часть консоли).
¨ Функция 01h. Ввод одиночного символа с эхом.
Вводит символ из стандартного устройства ввода и отображает его на устройстве стандартного вывода. Ввод каждого символа сопровождается перемещением курсора вправо на следующую позицию. При отсутствии символа ждёт ввода. При наборе строки обрабатываются управляющие клавиши: BS (шаг назад без удаления символа, AL = 08h), TAB (табуляция, AL = 09h), ENTER (переход на начало текущей строки, AL = 13h). Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет обработку . Для чтения расширенного кода ASCII требует повторного выполнения функции.
¨ Функция 06h. Ввод одиночных символов из стандартного устройства ввода и вывод одиночных символов на стандартное устройство вывода.
Режим работы определяется содержанием регистра DL в момент вызова функции: DL = FF – режим ввода, DL = <FFh – 00h > – режим вывода соответствующего этому коду символа. В режиме вывода коды ASCII: 07h – звонок, Dh – возврат каретки, Ah – перевод строки, рассматриваются как управляющие и выполняются соответствующие им действия.
Если вводимый символ в устройстве ввода присутствует, то он помещается в AL (без эха) с установкой флага ZF = 0, иначе ZF = 1. Отличительным качеством функции 06h является то обстоятельство, что она, просматривая устройство ввода, не останавливает программы (является асинхронной), если не обнаруживает в нём символа, а просто устанавливает флаг ZF = 1. Допускает перенаправление ввода-вывода. Для чтения расширенного кода ASCII требуется повторное выполнение функции.
Вызов: AH =06h, Int 21h.
ZF = 1 – устройство ввода пустое.
Вывод: DL = FE¸00. Код в регистре DL является одновременно и кодом выводимого символа.
¨ Функция 07h. Нефильтрованный ввод символа без эха.
Вводит символ из стандартного устройства ввода без его отображения на экране. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Не выполняет отработку . Для чтения расширенного кода ASCII требует повторное выполнение функции. Функция, как правило, используется для ввода пароля с целью защиты программы от несанкционированного запуска
¨ Функция 08h. Ввод символа без эха.
Вводит символ из стандартного устройства ввода. При отсутствии символа ждёт его ввода. Допустимо перенаправление ввода. Для чтения расширенного кода ASCII требует повторное выполнение функции. Если ввод не перенаправлен, чувствительна к (иначе надо предварительно включить режим Break). Как и функция 07h, используется для ввода пароля. Пример использования данной функции будет рассмотрен в одной из программ этой работы.
Вызов: AH = 08h, Int 21h.
Вывод: AL = код символа.
¨ Функция Ah. Буферизованный ввод с клавиатуры.
Вводит строку байт из устройства стандартного ввода в буфер пользователя по адресу DS:DX, с отображением на устройстве стандартного вывода. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку (иначе надо предварительно включить режим Break). Функция допускает редактирование данных при их вводе клавишами: Backspace (отмена последнего символа), Exc (отмена всего набранного текста), F5 (запоминает текущую строку как подсказку), F3 (восстанавливает подсказку для ввода). Ввод символов строки заканчивается нажатием клавиши , код которой (0Dh) вводится в качестве последнего символа в отведённый буфер.
Структура буфера (резервируется в сегменте данных): байт 0 – назначаемая пользователем максимальная длина строки (1-254) с учётом символа CR (код Dh), байт 1 – число реально введённых символов без учёта символа CR, байт 2 и далее – строка. В следующем примере приведена процедура In_string ввода строки в буфер, емкостью 50 символов. Она возвращает адрес первого символа строки в регистре DX, а число символов в регистре CX.
Buf DB 50. 50 DUP(?) ;Буфер пользователя
lea dx,[Buf] ;Адрес буфера пользователя
mov ah,0Ah ;Запрос функции 0Ah
int 21h ;Вызов DOS
mov cl,[Buf+1] ;Поместить счётчик символов в cx
add dx,2 ;Сделать dx указателем строки
¨ Функция 0Bh. Проверка состояния ввода.
Проверяет наличие символа в буфере клавиатуры. Допустимо перенаправление ввода. Если ввод не перенаправлен, выполняет отработку . Это даёт возможность организовать с её помощью аварийное завершение программы (нажатием комбинации ) с циклом, состоящим из чисто процессорных команд, включив предварительно в цикл вызов функции Bh.
Возврат: Если символа нет, то AL = 0, если символ ждет, то AL = FFH.
¨ Функция 0Ch. Вызов служебной функции DOS для ввода данных с предварительной очисткой буфера клавиатуры. Допускает переопределение ввода.
Вызов: AH = 0Ch, Int 21h,
AL = номер функции ввода: 01, 07, 08, 0Ah (если AL = 0, то только очистка), DS:DX = адрес буфера, если AL = 0Ah.
Выход: AL = байт входных данных (если при вызове Al = 0Ah, данные помещаются в буфер).
¨ Функция 3Fh. Ввод данных из файла или устройства.
Универсальная функция ввода данных в буфер с указателем DS:DX из источника, определённого дескриптором в регистре BX. Допускает переопределение ввода. В регистре CX указывается число байтов, которое необходимо ввести. Пример использования.
In_Area DB 20 DUP(?)
mov ah,3Fh ;Запрос функции 3Fh
mov bx,00h ;Дескриптор ввода (клавиатуры)
mov cx,20 ;Число пересылаемых байт
lea dx,[In_Area] ;Адрес буфера ввода
int 21h ;Вызов функции DOS
sub cx,2 ;Фактически введено
Команда Int 21h ожидает окончания ввода символов, которое фиксируется нажатием клавиши Enter. После ввода текста и нажатия клавиши Enter в буфер In_Aria автоматически вводятся два управляющих символа: CR (код 0Dh) и LF (код 0Ah). Вследствие данной особенности максимальное число символов и размер буфера ввода должны содержать место для двух дополнительных символов. При успешном завершении операции флаг CF = 0, а в регистре AX устанавливается число байтов, введённых с клавиатуры (плюс два дополнительных символа). Если CF = 1, то в регистре AX содержится возвратный код ошибки. Это либо 5 (отказ в доступе), либо 6 (неверный дескриптор).
К особенностям использования данной функции следует отнести автоматический переход на новую строку по окончании ввода данных.
7.2.3. ФУНКЦИИ DOS ВЫВОДА ДАННЫХ НА ЭКРАН
DOS предоставляет следующие способы вывода данных на экран:
— использование функций Int 21h (02h, 06h, 09h), обеспечивающих посимвольный ввод с клавиатуры в разных режимах;
— обращение к экрану, как к файлу, с помощью функции 40h.
¨ Функция 02h. Вывод одиночного символа.
Выводит символ, находящийся в регистре DL, на экран, после чего курсор сдвигается на одну позицию вправо. Для вывода строки функцию следует использовать в цикле. Допустимо перенаправление вывода. Выполняет обработку при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа. Эта функция выводит и управляющие ASCII-символы с кодами 07h, 08h, 09h, 0Ah, 0Dh. Символ с кодом 07h (bell, звонок) вызывает звуковой сигнал, с кодом 08h (backspace, забой) – возвращает курсор на одну позицию влево, с кодом 09h (tab, табуляция) – смещает курсор на одну позицию вправо, кратную 8. Действия управляющих клавиш с кодами Ah и Dh рассматривались ранее.
Вызов: AH = 02h, Int 21h.
Выход: DL = ASCII – код символа,
AL = код последнего записанного символа (кроме случая, когда DL = 09, тогда возвращается значение 20h).
Использование данной функции рассмотрим на примере процедуры перехода на новую строку.
mov ah,2 ;Запрос функции 02h
mov dl,13 ;Возврат каретки
int 21h ;Вызов DOS
mov dl,10 ;перевод строки
int 21h ;Второй вызов DOS
¨ Функция 09h. Вывод строки.
Выводит строку символов на устройство стандартного вывода (используется в системных программах для вывода на экран информационных сообщений). Строка должна заканчиваться символом $ (код24h), который служит признаком конца строки, и сам не выводится. Допустимо перенаправление вывода. В сообщение могут быть включены и управляющие коды (07h, 08h, 09h, 0Ah, 0Dh), которые вызывают соответствующие им действия (см. функцию 02h). Допустимо использование Exc-последовательностей. Функция выполняет обработку при вводе этой комбинации с клавиатуры перед выводом каждого 64-го символа.
lea dx,[Promt] ;Адрес строки Promt: DS:DX
mov ah,09h ;Запрос функции 09h
int 21h ;Вызов DOS
¨ Функция 40h. Вывод данных в файл или в устройство.
Универсальная функция вывода данных из буфера пользователя в сегменте данных в файл или на устройство, дескриптор которого указывается в регистре BX. Дескриптор 1, закреплённый за стандартным устройством вывода, обеспечивает перенаправление вывода. Значение регистра CX определяет число байтов, которые должны быть выведены, а пара регистров DS:DX указывает адрес выводимых данных. Управляющие коды 08h, 0Ah, 0Dh и некоторые другие приводят к выполнению соответствующих им действий. После завершения вывода при CF = 0 регистр AX содержит число действительно выведенных байтов, а при CF =1 – возвратный код ошибки. Как и при использовании функции 3Fh, это коды ошибок 5 или 6. Пример использования.
Out_Area DB 20 DUP(?)
mov ah,40h ;Запрос функции 40h
mov bx,01 ;Дескриптор дисплея
mov cx,20 ;Число пересылаемых байт
lea dx,[Out_Area] ;Адрес буфера для выводимого сообщения
int 21h ;Вызов DOS
7.2.4. РАСШИРЕННЫЕ КОДЫ ASCII И УПРАВЛЕНИЕ ПРОГРАММОЙ С КЛАВИАТУРЫ
Как уже отмечалось в п 7.2.2, рассмотренный процесс считывания ASCII-кодов клавиш клавиатуры с помощью системных функций DOS относится к алфавитно-цифровым клавишам, за которыми закреплены ASCII-таблицей отображаемые символы (буквы, цифры, знаки препинания и др.). Кроме них, на клавиатуре персонального компьютера имеется ряд клавиш, которым не назначены какие-либо отображаемые символы. Это, например, функциональные клавиши . , клавиши управления курсором , , . , , , специальные клавиши , , а также использующие на практике различные сочетания клавиш с , и . В этом случае, в качестве scan-кода клавиши или какой-либо комбинации из них выступает также старший байт кодового слова, но уже при нулевом младшем байте (нулевом коде ASCII). Например, при нажатии клавиши в кольцевой буфер ввода клавиатуры поступает код 3B00h, а клавиши – 4700h.
Двухбайтовые коды клавиш, содержащие на месте кода ASCII – ноль, называются расширенными кодами ASCII. Эти коды (и соответствующие им клавиши) широко используются для управления программами. Для доказательства этого утверждения достаточно указать на популярную оболочку DOS – Norton Commander. Широкое использование в компьютерах интерактивных средств требовало расширение возможностей ввода с клавиатуры управляющей информации, которую программа должна отличать от вводимого текста. Поэтому расширенные коды ASCII генерируются и всеми алфавитно-цифровыми клавишами, если они нажимаются совместно с клавишей . В табл. 2.2 приведены значения расширенных ASCII-кодов для одиночных клавиш.
Расширенные коды для функциональных клавиш
Клавиша
Код (hex)
Клавиша
Код (hex)
Клавиша
Код (hex)
Клавиша
Код (hex)
Правая часть клавиатуры.
«Num Lock-выкл»
В составе комбинации Alt+
Рассмотренные выше функции DOS, предназначенные для посимвольного ввода данных с клавиатуры, позволяют работать и с расширенными кодами ASCII. Однако программа при этом должна вызывать функцию DOS дважды. Первый вызов всегда возвращает младший байт и, если он равен нулю, то необходимо повторить вызов этой же функции для вывода старшего байта. Это и будет информационный байт расширенного кода ASCII, который можно использовать для управления программой.
Обратим здесь внимание на важный момент! Расширенный код ASCII можно считать, если программа будет настроена на проверку нулевого значения младшего байта для каждого нажатия клавиши. Пример использования функциональных клавиш для управления программой показан в листинге 2.1.
Листинг 2.1. Фрагмент программы, демонстрирующий выполнение альтернативных действий на основе анализа расширенных кодов ASCII
mes1 DB 13,10,’Сообщение $’
mes2 DB 13,10,’Сообщение $’
mes3 DB 13,10,’Сообщение $’
;Ожидаем нажатия клавиши
again: mov ah,08h ;Функция ввода одиночного символа без эха
int 21h ;Первый вызов DOS
cmp al,0 ;Расширенный ASCII код?
mov ah,08h ;Да, введём старший байт
int 21h ;Повторный вызов DOS
cmp al,3B ;Нажата F1?
cmp al,54h ;Нажата ?
cmp al,1Eh ;Нажата ?
jmp again ;Нажато незапланированное
F1: ;Вывод сообщения mes1
Shift_F1: ;Вывод сообщения mes2
Alt_A: ;Вывод сообщения mes3
Exit: ;Завершение программы
7.2.5. СТРОКОВЫЕ КОМАНДЫ. ОБЩАЯ ХАРАКТЕРИСТИКА
Строкой или литералом в языке ассемблера называется последовательность букв, цифр и других символов, заключённых в кавычки или апострофы (двойные кавычки). Следует отметить, что иногда понятие строки трактуется в расширительном смысле, а именно, как последовательность байтов, которые могут либо представлять, либо не представлять ASCII-символы.
Строковые команды, несмотря на синонимичное название со строковыми переменными, предназначены для обработки не только ASCII-строк, но и вообще блоков байтов, одинарных или двойных слов, каждое из которых хранится в памяти в двоичном коде.
Строковые команды представлены в табл. 3.1 и по своему назначению делятся на две группы:
— команды для поиска и сравнения данных (Scas, Cmps).
Любая строковая команда может оперировать как байтами, так и словами, что отражается в мнемокоде команды (например: movsb, movsw, movsd). Все строковые команды, в отличие от других команд процессора ix86, используют для выполнения своих функций одни и те же регистры:
Команды обработки строк
Название команды и её мнемокод
Действие
Тип исполь-зуемого префикса
Влияние на флаги
Lods src – Загрузка Acc из строки
src=byte ds:si Lodsb
src=word ds:si Lodsw
src=dword ds:si Lodsd
_
Stos dst – Сохранение Acc в строке
dst=byte es:di Stosb
dst=word es:di Stosw
dst=dword es:di Stosd
Movs dst,src – Пересылка элемента строки
dst=byte es:di, src=byte ds:si Movsb
dst=word es:di, src=word ds:si Movsw
dst=dword es:di, src=dword ds:si Movsd
Scas dst – Поиск элемента в строке
dst=byte es:di Scasb
dst=word es:di Scasw
dst=dword es:di Scasd
Все флаги операции сравнения
Cmps dst, src – Сравнение элементов строк
src=byte ds:si, dst=byte es:di Cmpsb
src=word ds:si, dst=word es:di Cmpsw
src=dword ds:si, dst=dword es:di Cmpsd
src—dst .
Все флаги операции сравнения
При этом индексные регистры si(esi) и di(edi) определяют смещения элементов строк в сегментах данных, определяемых регистрами ds и es соответственно. Установите es = ds, если это не противоречит другим условиям реализации программы, что позволит вам не беспокоиться о корректной адресации сегментов памяти. Необходимо помнить, что в строковых инструкциях приёмник – строка es:di(edi) не допускает переопределение, а источник – строка ds:si(esi), допускает переопределение на es:si(esi).
Каждая из строковых команд выполняет операцию только над парой элементов двух строк (или над одним для команд Lods, Stos, Scas) и автоматически настраивается на обработку соседних элементов, обеспечивая продвижение по строке в нужном направлении, а именно:
Здесь величина d определяется согласно правилу:
Тип операнда Флаг направления
Префикс повторения, помещённый непосредственно перед строковой командой, заставляет её циклически выполняться определённое число раз до реализации заданного условия. Существуют три командных префикса:
— rep (repeat) – повторять, пока cx ¹ 0;
Префиксы используют регистр CX как счётчик числа циклов (беззнаковое число), которое должно быть записано в CX до начала выполнения строковой команды. Счётчик CX декрементируется на 1 после выполнения строковой команды, но проверяется перед её выполнением. Если CX = 0, то строковая команда не выполняется ни разу. Префиксы repe и repne дополнительно выставляют флаг нуля ZF после выполнения строковой операции.
В листинге 2.2. рассматривается использование строковой команды сравнения cmpsb на примере программы с паролем. Идея простейшей защиты программы от несанкционированного запуска заключается в том, что где-то в программе записывается ключевое слово-пароль, и программа, начав работать, требует ввода этого слова с клавиатуры. Если пользователь ввёл пароль правильно, программа продолжит свою работу, иначе попросит ввести его заново или завершится. Ввод пароля обычно осуществляется функцией DOS, не отображающей вводимые символы на экране (обычно 07h или 08h) и заканчивается нажатием клавиши .
Листинг 2.2. Фрагмент программы с паролем.
password DB ‘camel’ ;Пароль
string DB 80 DUP(?)
promt DB 13,10,’Введите пароль: $’
OK DB 13,10,’Работаем!$’
start: mov ax,@data
begin: mov ah,09h ;Вывод запроса на ввод пароля
mov dx,offset promt ;Адрес запроса
mov bx,0 ;Инициализация индексирования ввода
pass: mov ah,08h ;Функция ввода символа в AL без эха
je compare ;Да, на сравнение
mov [string+bx],al ;Нет, сохраним символ
mov dl,’*’ ;Запишем на экран *
jmp pass ;Повторять
;Сравнение введённого пароля с действительным (сравнение строк)
compare: push ds ;Установить ES на сегмент данных
mov si,offset string ;DS:SI- начало string
mov di,jffset password ;ES:DI- начало password
cld ;DF=0- просмотр вперёд
mov cx,pass_len ;Установить счётчик сравнения
repe cmpsb ;Сравнивать, пока
;пока символы двух строк совпадают, но не более CX раз)
jne err ;Строки не равны
Вывод сообщения ОК, подтверждающего правильность пароля
mov dx,offset OK
exit: mov ax,4C00h ;Ввод функции 4С для завершения программы
err: jmp begin ;Повторить ввод пароля
Логика построения программы поясняется подробными комментариями. В программе ввод пароля выполняется в бесконечном цикле, поэтому пользователь, не знающий пароля и запустивший программу, для выхода из неё вынужден будет нажать комбинацию клавиш .
7.3. ЗАДАНИЯ К РАБОТЕ. ПОДГОТОВКА И ВЫПОЛНЕНИЕ
¨ Задания к работе
1) Ввести строку из произвольных ASCII-символов и произвести её сортировку под управлением функциональных клавиш: – по возрастанию; – по убыванию; – завершение программы. Работу программы отобразить на экране.
2) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки SYMBOL. Если подстрока найдена, то её необходимо удалить. Вновь полученную строку вывести на экран. Если подстрока не найдена, вывести сообщение NOT_FOUND. Программу защитить паролем.
3) Ввести строку из произвольного числа символов. Выполнить преобразование символьной строки в её цифровой аналог на основе ASCII-кодов, после чего произвести поиск максимального кода. Работу программы отобразить на экране и защитить паролем.
4) Ввести строку из произвольных ASCII-символов и произвести её сортировку к виду, включающему четыре части разделённые пробелами: цифры, буквы прописные, буквы строчные, все другие символы. Работу программы отобразить на экране и защитить паролем.
5) Ввести строку из нескольких слов, разделённых пробелами. Слова включают в произвольном порядке цифры, строчные и прописные латинские буквы. Отредактированная строка включает слова, начинающиеся с прописной буквы (остальные строчные). Цифры из слов должны быть удалены. Программу защитить паролем.
6) Ввести строку из произвольных ASCII-символов и выполнить с ней преобразования, задаваемые нажатием функциональных клавиш: – изменение порядка следования символов исходной строки на обратный, – замена строчной буквы на прописную и обратно, – завершение программы.
7) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки COMPUTER. Если такой подстроки нет, то данную подстроку ввести в начало исходной строки и вывести на экран. В противном случае дать сообщение There is. Программу защитить паролем.
Добавление и удаление элементов из неупорядоченного массива. Элементы последовательно один за другим вводятся с клавиатуры. При этом, если такой элемент отсутствует в массиве (первоначально он пуст), то он вводится в конец списка, в противном случае, он удаляется из него, а оставшиеся элементы сдвигаются влево (в сторону младших адресов) на одну позицию. Список элементов постоянно отображается на экране. Выход из программы осуществляется с помощью клавиши .
9) Ввести строку из произвольного числа символов. Выполнить преобразование символьной строки в её цифровой аналог на основе ASCII-кодов, после чего произвести поиск минимального кода. Работу программы отобразить на экране и защитить паролем.
10) Ввод с клавиатуры на экран произвольного текста с одновременной записью в буфер. Реализовать элементы редактирования: стирание последних символов клавишей Backspace, контроль над прописной буквой первого слова нового предложения (ввести признак начала предложения). При ошибке строчная буква заменяется прописной. Переход на новую строку осуществляется клавишей . Управление: – вывод копии отредактированного текста из буфера, – выход из программы.
11) Ввод с клавиатуры на экран произвольного текста с одновременной записью в буфер. Программа демонстрирует переход на новую строку одним из двух способов:
– нажатие клавиши , если последнее введённое слово пересекло границу в 40 символов. В этом случае на новую строку автоматически переносится всё последнее слово. После перехода на новую строку вывод текста может быть продолжен в обычном порядке. Выход из программы с помощью клавиши .
12) Ввести строку из произвольного числа символов и произвести в ней поиск подстроки AUTOMATON. Если такой подстроки нет, то в начало исходной строки поместить символ @, а в её конец дописать подстроку и вывести на экран. В противном случае дать сообщение There is. Программу защитить паролем.
13) Программа проверки работоспособности ОЗУ для заданной области памяти данных с использованием шахматного теста. Тест предусматривает запись в ячейки с чётными адресами числа 0AAh, а в нечётные – 55h. В результате последующего считывания осуществляется проверка записанной информации. При обнаружении сбоя запоминается адрес данной ячейки (для проверки выполнения последнего требования использовать прогон программы в отладчике TD).
14) Программа проверки работоспособности ОЗУ для заданной области памяти с использованием сканирующего теста. Тест предусматривает запись байта 00h с последующим считыванием и проверкой, затем те же действия выполняются с числом 0FFh. По результатам теста формируется массив из адресов ячеек, в которых обнаружен сбой (для проверки выполнения последнего требования использовать прогон программы в отладчике TD). Программу оформить как com-файл.
15) Разработать программу, преобразующую все символы введённой строки (в строке представлены произвольные алфавитно-цифровые символы) из нижнего регистра клавиатуры в верхний.
¨ Подготовка и выполнение:
a) ознакомиться с методическими рекомендациями к лабораторной работе и соответствующими тематическими разделами в рекомендуемой литературе;
б) разработать и отладить программу в соответствии с индивидуальным заданием;
в) программа, по возможности, должна обеспечивать удобный экранный интерфейс с пользователем при её демонстрации;
г) отчёт о выплненной работе представляет собой:
– индивидуальное задание на разработку программы;
– листинг программы с подробными комментариями и описанием её работы.
7.4. КОНТРОЛЬНЫЕ ВОПРОСЫ
1. Что такое дескриптор? Сколько дескрипторов определено в DOS и как ими пользоваться?
2. Какие функции DOS можно использовать для ввода символов с клавиатуры в регистр AL процессора?
3. Назовите функции DOS, осуществляющие ввод строки символов с клавиатуры в память данных.
4. Какие функции DOS осуществляют операцию вывода на экран:
– одиночных символов из регистра DL процессора;
– строки символов из памяти данных?
5. Напишите процедуру перевода курсора на новую строку с помощью функции 02h DOS.
6. Что такое скан-код клавиши и чем он отличается от расширенного кода ASCII? Как нужно организовать вызовы соответствующей функции DOS для получения расширенного ASCII-кода?
7. Каким сегментным регистрам должен адресоваться сегмент данных, в котором располагается:
8. Какие строковые команды влияют на флаги, а какие нет?
9. Перечислите префиксы повторения строковых команд и их возможные сочетания друг с другом.
10. В какой фазе исполнения команды происходит проверка счётчика на равенство нулю при выполнении:
– строковой команды с префиксом повторения;
– команды управления циклом Loop ?
Что происходит с исполнением этих команд, если счётчик СХ инициализирован нулём?
Dos fn 07h: нефильтрующий консольный ввод без эха
Способы ввода данных с клавиатуры
Процесс ввода информации в ассемблерных программах осуществляется аналогично выводу. Ниже описан ряд функций прерывания 21h, использующихся для ввода информации с клавиатуры.
Ввод с клавиатуры.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). Ввод расширенных клавиш ASCII (F1-F12, PgUp, курсор и т.п.) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.
Нефильтрующий консольный ввод без эха.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не фильтрует: Не проверяет на Ctrl-Break, backspace и т.п. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Консольный ввод без эха.
Выход: AL= символ, полученный с клавиатуры
Описание: Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23H. Необходимо вызывать дважды для ввода расширенного символа ASCII.
Буферизированный ввод строки.
DS:DX=адрес входного буфера (смотри ниже)
Выход: буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)
Описание: При входе буфер по адресу DS:DX должен быть оформлен следующим образом:
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 (буфер остается неизменным).
Ввод с очисткой
AL= номер функции ввода DOS (01H, 06H, 07H, 08H или 0aH)
Описание: Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа. Следующие значения допустимы в AL: 01H Ввод с клавиатуры; 06H Ввод с консоли; 07H Нефильтрующий без эха; 08H Ввод без эха; 0aH Буферизованный ввод.
Далее программы будут оформляться в виде COM.
Рассмотрим программу которая осуществляет ввод строки с клавиатуры и заменяет все буквы «а» на заглавные, причем пробелы удаляются.
INT 20H: завершить программу
Это прерывание используется для выхода из программы и возврата управления родительскому процессу (обычно интерпретатору команд DOS — COMMAND.COM). Оно восстанавливает значения управляющих векторов INT 22H INT 23H INT 24H Оно также сбрасывает все файловые буфера (если длина файла изменилась, то файл должен быть предварительно закрыт).
Важно:
Регистр CS должен содержать значение PSP завершающегося процесса. Если ваш CS не равен PSP, вы можете выдать JMP или RET на PSP:0000.
Рекомендуется использовать функцию 4cH Terminate, чтобы избежать трудностей, связанных с неравенством CS и PSP. Она позволяет также задать код выхода. Программы COM-формата обычно выполняются при CS=PSP, так что им можно выдавать INT 20H в любой момент. EXE-программы могут выдавать FAR JMP или FAR RET, чтобы передать управление на PSP:0000, где содержится инструкция INT 20H.
INT 21H: сервис DOS
Это прерывание служит главным входом большинства функций DOS.
Программа, запрашивающая сервис DOS, должна подготовить всю необходимую информацию в регистрах и управляющих блоках, указать в регистре AH номер желаемой функции DOS и затем вызвать прерывание INT 21H.
- Функция DOS 00H: завершить программу
- Функция DOS 01H: ввод с клавиатуры **
- Функция DOS 02H: вывод на дисплей**
- Функция DOS 03H: ввод AUX
- Функция DOS 04H: вывод AUX
- Функция DOS 06H: Обмен с консолью*
- Функция DOS 07H: Нефильтрующий консольный ввод без эха*
- Функция DOS 08H: Консольный ввод без эха*
- Функция DOS 09H: Выдать строку***
- Функция DOS 0aH: буферизованный ввод строки*
- Функция DOS 0bH: проверить статус ввода*
- Функция DOS 0cH: ввод с очисткой*
- Функция DOS 0dH: Сбросить диск*
- Функция DOS 0eH: Выбрать умалчиваемый диск DOS
- Функция DOS 0fH: открыть файл через FCB
- Функция DOS 10H: Закрыть файл через FCB
- Функция DOS 11H: Найти 1-й совпадающий файл через FCB
- Функция DOS 12H: Найти следующий совпадающий файл через FCB
- Функция DOS 13H: Удалить файл через FCB
- Функция DOS 14H: читать последовательный файл через FCB
- Функция DOS 15H: писать последовательный файл через FCB
- Функция DOS 16H: создать файл через FCB
- Функция DOS 17H: Переименовать файл через FCB
- Функция DOS 19H: дать умалчиваемый диск DOS
- Функция DOS 1aH: установить адрес DTA*
- Функция DOS 1bH: дать информацию FAT (текущий диск)*
- Функция DOS 1cH: дать информацию FAT (любой диск)*
- Функция DOS 21H: читать запись произвольного файла
- Функция DOS 22H: писать запись произвольного файла
- Функция DOS 23H: дать размер файла через FCB*
- Функция DOS 24H: установить адрес блока произвольного файла
- Функция DOS 25H: установить вектор прерывания***
- Функция DOS 26H: создать префикс программного сегмента
- Функция DOS 27H: читать блок произвольного файла**
- Функция DOS 28H: писать блок произвольного файла
- Функция DOS 29H: Разобрать имя файла
- Функция DOS 2aH: дать дату DOS*
- Функция DOS 2bH: установить дату DOS*
- Функция DOS 2cH: дать время DOS*
- Функция DOS 2dH: установить время DOS*
- Функция DOS 2eH: установить/сбросить переключатель верификации
- Функция DOS 2fH: дать текущий DTA
- Функция DOS 30H: дать номер версии DOS*
- Функция DOS 31H: завершиться и остаться резидентным — KEEP*
- Функция DOS 32H: дать дисковую информацию DOS (недокументировано)
- Функция DOS 33H: установить/опросить уровень контроля прерывания DOS*
- Функция DOS 34H: адрес статуса реентерабельности DOS
- Функция DOS 35H: дать вектор прерывания***
- Функция DOS 36H: дать свободную память диска*
- Функция DOS 37H: установить/опросить символ-переключатель (недокументировано)
- Функция DOS 38H: дать/установить информацию страны
- Функция DOS 39H: создать новое оглавление — MKDIR
- Функция DOS 3aH: Удалить оглавление — RMDIR
- Функция DOS 3bH: установить умалчиваемое оглавление DOS — CHDIR
- Функция DOS 3cH: создать описатель файла
- Функция DOS 3dH: открыть описатель файла
- Функция DOS 3eH: Закрыть описатель файла
- Функция DOS 3fH: читать файл через описатель
- Функция DOS 40H: писать в файл через описатель
- Функция DOS 41H: Удалить файл*
- Функция DOS 42H: установить указатель файла — LSEEK
- Функция Функция DOS 43H: установить/опросить атрибут файла — CHMOD*
- Функция DOS 44H: управление вводом-выводом устройства — IOCTL
- Функция DOS 45H: Дублировать описатель файла — DUP
- Функция DOS 46H: переназначить описатель — FORCDUP
- Функция DOS 47H: дать умалчиваемое оглавление DOS
- Функция DOS 48H: распределить память (дать размер памяти)
- Функция DOS 49H: Освободить блок распределенной памяти***
- Функция DOS 4aH: Сжать или расширить блок памяти
- Функция DOS 4bH: выполнить или загрузить программу — EXEC
- Функция DOS 4cH: завершить программу — EXIT
- Функция DOS 4dH: дать код выхода программы — WAIT
- Функция DOS 4eH: Найти 1-й совпадающий файл
- Функция DOS 4fH: Найти следующий совпадающий файл
- Функция DOS 54H: дать переключатель верификации DOS
- Функция DOS 56H: Переименовать/переместить файл*
- Функция DOS 57H: установить/опросить время/дату файла*
- Функция DOS 59H: дать расширенную информацию об ошибке
- Функция DOS 5aH: создать уникальный временный файл
- Функция DOS 5bH: создать новый файл*
- Функция DOS 5cH: блокировать/разблокировать доступ к файлу
- Функция DOS 5eH: различные сетевые функции
- Функция DOS 5fH: переназначение устройств в сети
- Функция DOS 62H: дать адрес префикса программного сегмента**
Лабораторная работа №6 Ввод информации с клавиатуры терминала
Назва | Лабораторная работа №6 Ввод информации с клавиатуры терминала |
Дата | 03.08.2012 |
Розмір | 187.24 Kb. |
Тип | Лабораторная работа |
Лабораторная работа №6 Ввод информации с клавиатуры терминала Для уверенной работы с машиной полезно понимать, каким образом вводятся, куда попадают и как обрабатываются символы, вводимые с клавиатуры. Процесс взаимодействия системы с клавиатурой продемонстрирован на рис. Адрес ПОП — вектора прерывания 09h (ячейки 00:24h и 00:26h) Работой клавиатуры управляет специальная электронная схема — контроллер клавиатуры. В его функции входит распознавание нажатой клавиши и помещение закрепленного за ней кода в свой выходной регистр (порт), обычно с номером 60h. Код клавиши, поступающий в порт, называется скен-кодом и является, по существу, порядковым номером клавший, хотя последовательность скен-кодов не всегда совпадает с порядком расположения клавиш на клавиатуре. При этом каждой клавише присвоены как бы два скен-кода, отличающиеся друг от друга на 80h. Один скен-код (меньший, код нажатия) засылается контроллером в порт 60h при нажатии клавиши, другой (больший, код отпускания) — при ее отпускании. Скен-код однозначно указывает на нажатую клавишу, однако по нему нельзя определить, работает ли пользователь на нижнем или верхнем регистре, а также вводит ли он латинские или русские буквы. С другой стороны, скен-коды присвоены всем клавишам клавиатуры, в том числе управляющим клавишам , , , и др. Таким образом, очевидно, что определение введенного символа должно включать в себя не только считывание скен-кода нажатой клавиши, но и выяснение того, не были ли перед этим нажаты, например, клавиши (верхний регистр) или (фиксация верхнего регистра). Всем этим анализом занимается программа обработки прерываний от клавиатуры. Нажатие (а также и отпускание) любой клавиши вызывает сигнал аппаратного (внешнего) прерывания, заставляющий процессор прервать выполняемую программу и перейти на программу обработки прерывания (ПОП) от клавиатуры. Эта программа хранится по фиксированному адресу в постоянном запоминающем устройстве BIOS, являясь, таким образом, элементом «встроенного», или «зашитого» программного обеспечения. Процессор вместе с сигналом прерывания получает еще и тип прерывания, или его номер. За клавиатурой закреплен номер 09h. Адрес программы обработки прерываний от клавиатуры располагается; таким образом, и векторе 09h, занимающем слова с адресами 24h и 26 h (36-38 ячейки памяти). Получив тип прерывания и определив по нему адрес вектора, процессор извлекает из вектора адрес программы обработки прерываний и осуществляет переход на ее выполнение. Поскольку программа обработки прерываний от клавиатуры вызывается через вектор 09h, ее часто называют программой INT 09h (INT — от английского Interrupt, прерывание). Программа INT 09h, помимо порта 60h, работает еще с двумя областями оперативной памяти: кольцевым буфером ввода, располагаемым по адресам от 40h:1Eh до 40h:3Dh, куда, в конце концов, помещаются коды ASCII нажатых клавиш, и словом состояния (словом флагов) клавиатуры, находящимся по адресу 40h:17h, где фиксируется состояние управляющих клавиш ( , , и др.). Программа INT 09h, получив управление в результате прерывания от клавиатуры, считывает из порта 60h скен-код и анализирует его значение. Если скен-код принадлежит одной из управляющих клавиш, и, к тому же, представляет собой код нажатия, в слове флагов клавиатуры устанавливается бит (флаг), соответствующий нажатой клавише. Например, при нажатии правой клавиши в слове флагов устанавливается бит 0, при нажатии левой клавиши — бит 1, при нажатии любой клавиши -бит 2, а при нажатии (тоже любой) — бит 3. Биты флагов сохраняют свое состояние пока клавиши (по одиночке или в любых комбинациях) остаются нажатыми. Если управляющая клавиша отпускается, программа INT 09h получает скен-код отпускания и сбрасывает соответствующий бит в слове флагов. Кроме состояния указанных клавиш, в слове флагов фиксируются еще режимы , , и , а в 101-клавишной клавиатуре на компьютерах РС/АТ также состояния клавиш , -левая, -левая и режим паузы ( / ). При нажатии любой другой клавиши программа INT 09h считывает из порта 60h ее скен-код нажатия и по таблице трансляции скен-кодов в коды ASCII формирует двухбайтовый код, старший байт которого содержит скен-код, а младший — код ASCII. При этом если скен-код характеризует клавишу, то код ASCII определяет закрепленный за ней символ. Поскольку за каждой клавишей закреплено, как правило, не менее двух символов («а»и «А», «1» и «!», «2» и»@» и т.д.), то каждому скен-коду соответствуют, как минимум, два кода ASCII. В процессе трансляции программа INT 09h анализирует состояние флагов, так что если нажата, например, клавиша Q (скен-код 10h, код ASCII буквы Q — 51 h, а буквы q — 71h), то формируется двухбайтовый код 1071h, но если клавиша Q нажата при нажатой клавише (смена регистра), то результат трансляции составит 105lh. Тот же код 105lh получится, если при нажатии клавиши Q был включен режим (заглавные буквы), однако при включенном режиме и нажатой клавише образуется код 107lh, поскольку в такой ситуации клавиша на время нажатия переводит клавиатуру в режим нижнего регистра (строчные буквы). Полученный в результате трансляции двухбайтовый код засылается программой INT 09h в кольцевой буфер ввода, который служит для синхронизации процессов ввода данных с клавиатуры и приема их выполняемой компьютером программой. Объем кольцевого буфера составляет 15 слов, при этом дисциплина его обслуживания такова, что коды символов извлекаются из него в том же порядке, в каком они в него поступали. За состоянием буфера следят два указателя. В хвостовом указателе (слово по адресу 40:lCh) хранится адрес первой свободной ячейки, в головном указателе (40: lAh) — адрес самого старого кода, принятого с клавиатуры и еще не востребованного программой. В начале работы, когда буфер пуст, оба указателя — и хвостовой, и головной, указывают на первую ячейку буфера. Программа INT 09h, сформировав двухбайтовый код, помещает его в буфер по адресу, находящемуся в хвостовом указателе. после этого этот адрес увеличивается на 2, указывая опять на первую свободную ячейку. Каждое последующее нажатие на какую-либо клавишу добавляет в буфер очередной двухбайтовый код и смещает хвостовой указатель. Выполняемая программа, желая получить код нажатой клавиши, должна вызвать прерывание INT 16h, которое активизирует драйвер клавиатуры — BIOS. Драйвер считывает из кольцевого буфера содержимое ячейки, адрес которой находится в головном указателе, и увеличивает этот адрес на 2. Таким образом, программный запрос на ввод с клавиатуры фактически выполняет прием кода не с клавиатуры, а из кольцевого буфера. Хвостовой указатель, перемещаясь по буферу в процессе занесения в него кодов, доходит, наконец, до конца буфера (адрес40h:ЗСh). В этом случае при поступлении очередного кода адрес в указателе не увеличивается, а, наоборот, уменьшается на длину буфера. Тем самым указатель возвращается в начало буфера, после чего продолжает перемещаться по буферу до его конца, опять возвращается в начало и так далее по кольцу. Аналогичные манипуляции выполняются и с головным указателем. Равенство адресов в обоих указателях свидетельствует о том. что буфер пуст. Если при этом программа вызвала прерывание INT 16h, то драйвер клавиатуры будет ждать поступления кода в буфер, после чего он будет передан в программу. Если же хвостовой указатель, перемещаясь по буферу в процессе его заполнения, подошел к головному указателю «с обратной стороны» (это произойдет, если оператор нажимает на клавиши, а программа не выполняет запросы к драйверу клавиатуры), прием новых кодов блокируется, а нажатие на клавиши возбуждает предупреждающие звуковые сигналы. Если компьютер находится в пассивном состоянии ожидания команд DOS с клавиатуры, то за состоянием кольцевого буфера ввода следит командный процессор COMMAND.COM. Как только в буфере появляется код символа, командный процессор с помощью соответствующих системных программ переносит его в свой внутренний буфер командной строки, очищая при этом кольцевой буфер ввода, а также выводит символ на экран, организуя режим эхо-контроля. При получении кода клавиши (0Dh) командный процессор предполагает, что ввод команды закончен, анализирует содержимое своего буфера и приступает к выполнению введенной команды. При этом командный процессор работает практически лишь с младшими половинами двухбайтовых кодов символов, именно, с кодами ASCII. Если компьютер выполняет какую-либо программу, ведущую диалог с оператором, то, как уже отмечалось, ввод. данных с клавиатуры (а точнее — из кольцевого буфера ввода) и вывод их на экран с целью эхо-контроля организует эта программа, обращаясь непосредственно к драйверу BIOS (INT 16h) или к соответствующей функции DOS (INT 21h). Может случиться, однако, что выполняемой программе не требуется ввод с клавиатуры, а оператор нажал какие-то клавиши. В этом случае вводимые символы накапливаются (с помощью программы INT 09h) в кольцевом буфере ввода и, естественно, не отображаются на экране. Так можно ввести до 15 символов. Когда программа завершится, управление будет передано COMMAND.COM, который сразу же обнаружит наличие символов в кольцевом буфере, извлечет их оттуда и отобразит на экране. Такой ввод с клавиатуры называют вводом с упреждением. До сих пор речь шла о символах и кодах ASCII, которым соответствуют определенные клавиши терминала и которые можно отобразить на экране. Это буквы (прописные и строчные), цифры, знаки препинания и специальные знаки, используемые в программах и командных строках, например, [, $, # и др. Однако, имеется рад клавиш, которым не назначены какие-то отображаемые на экране символы. Это, например, функциональные клавиши , . ; клавиши управления курсором , , , , и др. Очевидно, что всем этим клавишам назначены определенные скен-коды. Но как их скен-коды транслируются в коды ASCII? В таблице трансляции, с которой работает программа INT 09h, всем таким скен-кодам соответствует нулевой код ASCII. Поэтому при нажатии, например, клавиши (скен-код 3Bh) в кольцевой буфер ввода поступает двухбайтовый код ЗВ00h, а при нажатии клавиши (скен-код 47h) — двухбайтовый код 4700h. Двухбайтовые коды, содержащие на месте кода ASCII ноль, называются расширенными кодами ASCII. Эти коды (и соответствующие им клавиши) широко используются для управления программами. Например, в оболочке DOS Norton Commander нажатие функциональных клавиш вызывает выполнение определенных операций: — вывод на экран справочника, -копирование файла, — его удаление и т.д. Программы, работающие с расширенными кодами ASCII, должны, очевидно, считав из кольцевого буфера ввода младший байт и убедившись, что он равен нулю, считать далее и старший байт (в сущности скен-код) и в зависимости от его значения выполнить соответствующее действие. Системные средства ввода данных с клавиатуры DOS предоставляет три уровня процедур ввода данных с клавиатуры:
Ввод с клавиатуры средствами файловой системы (INT 21h, функция 3Fh) осуществляется точно так же, как и чтение из файла. Обычно используется предопределенный дескриптор 0, закрепленный за стандартным устройством ввода (по умолчанию за клавиатурой). Число вводимых символов указывается в регистре СХ, однако ввод завершается лишь после того, как нажата клавиша , независимо от того, введено ли фактически меньше символов, чем было запланировано, или больше (последнее, естественно, может случиться лишь при неправильных действиях).Поэтому при вводе строк с клавиатуры нет необходимости заранее задавать их длину, достаточно загрузить в регистр СХ максимальную длину строки, например, 80 байт. В любом случае в регистре АХ возвращается число реально введенных байтов, при этом учитываются также и два байта (0Ah и 0Dh), поступающие во входной буфер при нажатии клавиши . Особая ситуация возникает, если попытаться ввести больше символов, чем затребовано функцией 3Fh. В процессе выполнения этой функции все вводимые символы тут же извлекаются из кольцевого буфера ввода и пересылаются в буфер DOS. Обнаружив во входном потоке коды клавиши , DOS пересылает из этого буфера в буфер пользователя в программе точно затребованное число символов (естественно, без кодов , которые располагаются в конце вводимой строки). Остальные символы остаются в буфере DOS, готовые к вводу. Фактически, если не принять специальных мер к очистке буфера, они поступят в программу при очередном запросе 3Fh, даже если оператор еще не начал вводить очередную порцию данных. Очевидно, что в этом случае будет нарушена синхронизация хода выполнения программы с работой оператора. Второй способ получения данных с клавиатуры в программу, с помощью функций DOS для посимвольного ввода, несколько более громоздок, но обеспечивает более разнообразные возможности. Всего используется 7 функций прерывания INT 21h: 0lh — ввод символа с эхом; 06h — прямой ввод — вывод через консоль; 07h — нефильтрованный ввод без эха; 08h — ввод символа без эха; 0Ah — буферизованный ввод строки с эхом; 0Bh — проверка состояния стандартного устройства ввода; 0Сh — сброс входного буфера и ввод. ^ INT 21h, функция 0lh. Ввод символа с эхом. Вводит символ из устройства стандартного ввода и отображает его на устройстве стандартного вывода. При отсутствии символа ждет ввода. Выполняет обработку /C. Для чтения расширенного кода ASCII требуется повторное выполнение функции. При вызове: AH=01h При возврате: АL=байт входных данных ^ INT 21h, функция 06h. Прямой ввод — вывод. Вводит из устройства стандартного ввода и выводит на устройство стандартного вывода все коды символов без вмешательства DOS. Для чтения расширенного кода ASCII требуется повторное выполнение функции. При отсутствии символа не ждет его ввода, а возвращает управление в программу. При вызове: AH=06h DL=код символа (00h — FEh) (при выводе) DL=FFh (при вводе) При возврате: АL=код символа (при вводе); если символа нет, то ZF=1 ^ INT 21h, функция 07h. Нефильтрованный ввод без эха. Вводит символ из устройства стандартного ввода без его отображения. При отсутствии символа ждет ввода. Не выполняет обработку /C. Для чтения расширенного кода ASCII требуется повторное выполнение функции. При вызове: AH=07h При возврате: АL=байт входных данных ^ INT 2lh, функция 08h. Ввод символа без эха. Вводит символ из устройства стандартного ввода без его отображения. При отсутствии символа ждет ввода. Для чтения расширенного кода ASCII требуется повторное выполнение функции При вызове: AH=08h При возврате: АL=байт входных данных ^ INT 2lh, функция OAh. Буферизованный ввод с клавиатуры. Вводит строку байт из устройства стандартного ввода в буфер пользователя с отображением на устройстве стандартного вывода. Строка должна заканчиваться символом возврата каретки (0Dh). Выполняет обработку /C. При вызове: AH=0Ah При возврате: Данные помещены в буфер. Формат буфера: байт 0 — ожидаемая длина строки байт 1 — фактическая длина введенной строки байт 2 и далее — строка, заканчивающаяся 0Dh. ^ INT 2lh, функция 0Bh. Проверка состояния ввода. Проверяет наличие символа от устройства стандартного ввода. Выполняет обработку /C. При вызове: AH=0Bh При возврате: AL=00h если символ не ждет AL=FFh если символ ждет ^ INT 2lh, функция 0Ch. Очистка входного буфера и ввод. Очищает кольцевой буфер клавиатуры и активизирует функцию ввода. При вызове: AH=0Ch АL=»номер требуемой функции ввода. Допустимы функции 01, 06, 07, 08, 0Ah DS:DX=адpec буфера (если AL=0Ah) При возврате: АL=байт входных данных (если при вызове AL=0Ah, данные помещаются в буфер) Функции 0lh, 06h, 07h и 08h при каждом вызове вводят в программу один символ из кольцевого буфера ввода; при необходимости ввести группу символов (строку) функции следует использовать в цикле. Различаются эти функции наличием или отсутствием эха, а также реакцией на ввод с клавиатуры сочетания /С. Функции 0lh и 06h отображают вводимые символы на экране (эхо); функции 07h и 08h этого не делают, что дает возможность вводить данные тайком от окружающих (например, пароль или ключ). Второе важное различие описываемых функций касается их реакции на ввод сочетания /C. При выполнении функций 0lh и 08h DOS проверяет каждый введенный символ и, обнаружив во входном потоке код /C (03h),аварийно завершает программу. Функции же 06h и 07h пропускают код /C в программу, не инициируя по нему никаких специальных действий. Такой метод ввода используется прикладными программами, если перед завершением в них должны быть выполнены определенные программные действия (сброс буферов на диск, модификация файлов и проч.). Аварийное завершение такой программы средства DOS по коду /C могло бы привести к нарушению ее работоспособности. Функция 0Ah передает в буфер пользователя отроку, введенную с клавиатуры; строка должна заканчиваться нажатием клавиши . Длина строки может достигать 254 символов. Вводимые символы отображаются на экране; при вводе /C происходит аварийное завершение программы. Функция 0Bh позволяет проверить наличие в кольцевом буфере ввода ожидающих символов. При обнаружении символов программа должна извлечь их из буфера одной из функций ввода; если символов нет, программа может продолжить выполнение. Такая методика используется в программах, носящих циклический характер, если требуется обеспечить управление ходом выполнения программы с клавиатуры терминала. В каждом шаге цикла после выполнения запланированных действий проверяется состояние кольцевого буфера ввода; если в течение предыдущего шага цикла оператор нажал на какую-либо клавишу, программа проанализирует введенный код и осуществит выход из цикла и переход в ту или иную точку; если же буфер оказывается пуст, циклическое выполнение продолжится. Функция 0Bh чувствительна к /C. Это дает возможность организовать с ее помощью аварийное завершение программы на тех ее участках, где выполняются чисто процессорные действия. Если, например, включить вызов функции 0Bh в цикл, .то при отсутствии ввода с клавиатуры цикл будет выполняться обычным образом, но после ввода /C программа аварийно завершится, хотя на выполняемом участке программы не используются функции ввода-вывода. Функция 0Сh служит для организации ввода с предварительной очисткой кольцевого буфера. Все функции, кроме 0Сh, вводят в программу наиболее старый из скопившихся в кольцевом буфере ввода символов, реализуя тем самым возможность ввода с упреждением. В этом режиме оператор может нажимать на клавиши еще до выдачи программой запроса на ввод; коды нажатых клавиш (не более 15) будут накапливаться в кольцевом буфере ввода и извлекаться оттуда в программу по мере выполнения ею запросов на ввод- В отличие от этого, функция 0Сh сначала очищает кольцевой буфер и лишь затем ожидает ввода символа с клавиатуры. В результате коды всех ранее нажатых (по предположению -случайно) клавиш теряются. Обычно функция ввода 0Сh стоит в программе непосредственно вслед за функцией вывода на экран символьной строки с предложением оператору вводить данные. В результате из кольцевого буфера убирается весь «мусор» от случайных нажатий, в программу же поступает лишь то, что вводится оператором после запроса программы. При этом режим ввода (с эхом или без него и т.д.) определяется тем, какая именно функция ввода (0lh, 06h, 07h, 08h или 0Ah) реализуется «внутри»функции 0Сh. Все функции DOS ввода с клавитуры допускают перенаправление ввода (из файла, последовательного порта, из вывода другой программы). Если требуется избавиться от этого качества, следует использовать файловую функцию ввода 3Fh и специально выделенный дескриптор. Функции 0lh, 07h, 08h и 0Ah являются синхронными, т.е. при отсутствии символа в кольцевом буфере ждут его ввода. Функция 06h позволяет определить состояние кольцевого буфера и при наличии в нем кода извлечь этот код и обработать его, а при отсутствии — продолжить выполнение программы. Функции 0lh, 06h, 07h и 08h позволяют вводить в программу расширенные коды ASCII. Для этого, обнаружив, что введенный код ASCII равен нулю, следует выполнить функцию повторно. Это дает возможность управления прикладными программами с помощью функциональных клавиш, а также сочетаний /цифра, /буква Функция 06h позволяет вводить в программу коды символов с помощью сочетания / (втом числе коды первых 32 символов кодовой таблицы и вторую половину кодовой таблицы). ^ Сравнительные характеристики функций DOS ввода с клавиатуры приведены в таблице.
|