МАРИЙСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

Кафедра ИиСП

Лабораторная работа № 4

по дисциплине:

«Программирование на языке Ассемблер»

Управление клавиатурой. Ввод символьных данных.

Утверждено

на заседании кафедры ИиСП

Зав кафедрой ИиСП

___________

Йошкар-Ола

2009

Цель работы: Изучить средства BIOS и DOS для ввода символов с клавиатуры. Написать процедуры ввода с клавиатуры для общего назначения.

КЛАВИАТУРА

Управление клавиатурой.

Клавиатура содержит интелевский микропроцессор, который воспринимает каждое нажатие на клавишу и выдает скан-код в порт A микросхемы интерфейса с периферией, расположенной на системной плате. Скан-код это однобайтное число, младшие 7 битов которого представляют идентификационный номер, присвоенный каждой клавише. На всех машинах, кроме AT, старший бит кода говорит о том, была ли клавиша нажата (бит = 1, код нажатия) или освобождена (бит = 0, код освобождения). Например, 7-битный скан-код клавиши B - 48, или 110000 в двоичной системе. Когда эта клавиша нажимается, то в порт A посылается код 10110000, а когда ее отпустили - код 00110000. Таким образом, каждое нажатие на клавишу дважды регистрируется в микросхеме 8255. И каждый раз микросхема 8255 выдает подтверждение микропроцессору клавиатуры. AT работает немного по-другому, посылая в обоих случаях один и тот же скан-код, но предваряя его кодом F0H, когда клавиша отпускается.

Когда скан-код выдается в порт A, то вызывается прерывание клавиатуры (INT 9). Процессор моментально прекращает свою работу и выполняет процедуру, анализирующую скан-код. Когда поступает код от клавиши сдвига или переключателя, то изменение статуса записывается в память. Во всех остальных случаях скан-код трансформируется в код символа, при условии, что он подается при нажатии клавиши (в противном случае, скан-код отбрасывается). Конечно, процедура сначала определяет установку клавиш сдвига и переключателей, чтобы правильно получить вводимый код (это "a" или "A"?). После этого введенный код помещается в буфер клавиатуры, который является областью памяти, способной запомнить до 15 вводимых символов, пока программа слишком занята, чтобы обработать их.

НЕ нашли? Не то? Что вы ищете?

Имеется несколько комбинаций клавиш, которые выполняют специ­альные функции и не генерируют скан-коды. Эти комбинации включают <Ctrl-Break>, <Ctrl-Alt-Del> и <PrtSc>, плюс <SysReq> для AT и <Ctrl-Alt-стрелка влево, - стрелка вправо, - CapsLock, -Ins> для PCjr.

Все остальные нажатия клавиш должны интерпретироваться Вашей программой и если они имеют специальное назначение, скажем сдвинуть курсор влево, то Ваша программа должна содержать код, обеспечивающий достижение этого эффекта.

Очистка буфера клавиатуры.

Перед выдачей программой запроса на ввод нужно очистить буфер клавиатуры, исключая посторонние нажатия клавиш, которые могли накопиться в буфере. Буфер может накапливать до 15 нажатий, т. е. он должен отвести по 2 байта на каждое нажатие.

Буфер клавиатуры имеет структуру очереди с постоянной длиной (FIFO), т. е. I вошел – I ушел. Он занимает непрерывную область адресов памяти. Два указателя хранят позиции головы и хвоста строки символов, находящихся в буфере в текущий момент. Новые нажатия клавиш запасаются в позициях, следующих за хвостом (в более старших адресах памяти). При заполнении последних ячеек буфера вновь начинается заполнение первых ячеек, т. е. голова строки имеет больший адрес, чем хвост. После заполнения буфера новые вводимые символы игнорируются и прерывание клавиатуры выдаёт гудок через динамик.

Когда указатель на голову установлен на I-й введённый символ, указатель на хвост установлен на позицию за последним введённым символом. Когда оба указателя равны, то буфер пуст. Для ввода 15 символов требуется 16-я пустая позиция (2 байта), которая всегда содержит код возврата каретки (ASCII 13) и скан-код клавиши «ENTER», равный 28. Эта позиция непосредственно предшествует голове строки символов.

32 байта буфера начинаются с адреса 0040:001E.

Указатель на голову по адресу: 0040:001A

Указатель на хвост по адресу: 0040:001C,

Для очистки буфера значения в этих ячейках нужно приравнять. Под каждый указатель отведено 2 байта, но используется только младший. Значения указателей меняются от 30 до 60.

Функция 0Сh прерывания 21h выполняет любую из функций ввода с клавиатуры 1,6,7,8 и А, но перед этим чистит буфер. Надо просто поместить номер функции ввода в AL (в этом примере - 1):

;----------очистка буфера перед нажатием клавиши

MOV AH, 0Ch ;выбираем функцию DOS 0Ch

MOV AL,1 ;выбираем функцию ввода символа

INT 21h ;чистим буфер, ждём ввода.

Проверка символов в буфере.

Можно проверить, был ли ввод с клавиатуры, не удаляя символа из буфера, т. е. сравнивая значения указателей головы и хвоста очереди символов на равенство.

Функция 0Bh прерывания 21h возвращает значение 0FFh в AL, если буфер содержит 1 или более символов и значение 0, если он пуст.

;------------проверка наличия символа в буфере

MOV AH, 0Bh ;номер функции

INT 21h ;вызов прерывания 21h

CMP AL,0FFh ;сравнение с 0FFh

JE GET_KEYSTROKE ;переход к метке

;GET_KEYSTROKE, если буфер

;пуст.

Функция 1 прерывания BIOS 16h выполняет то же + показывает, какой символ в буфере. Флаг нуля сбрасывается (ZF=1), если буфер пуст; и устанавливается (ZF=0),если имеется символ. Копия символа, находящегося в голове буфера, помещается в AX, но символ не удаляется.

; ------------проверка наличия символа в буфере

MOV AH,1 ;номер функции

INT 16h ;проверка наличия символа

JZ NO_CHAR ;переход, если ZF=1

;--------------проверяем расширенный символ или нет

CMP AL,0 ;это расширенный символ?

JE EXTENDED_CODE ;если да то перейти к метке

;EXTENDED_CODE.

Ввод символов без вывода их на экран.

Иногда эхо на экране нежелательно. Например, выбор пункта меню по нажатию клавиши («горячие» клавиши) или проверка символа на ошибку перед выводом его на экран (при использовании ограниченного набора специализированных символов).

Прерывание 21h DOS.

Функция 7 и функция 8 (определяют Ctrl – Break) – ожидают ввод символа, если буфер пуст, а когда он появляется, то его не выводят. Символ возвращается в AL. В случае расширенного кода прерывание повторяется и в AL появляется II-й байт расширенного кода.

;----------------получаем введенный символ

MOV AH,7 ;номер функции

NT 21H ;ожидаем ввод символа

CMP AL,0 ;проверка на расширенный код

JE EXTENDED_CODE ;если да, то на особую процедуру

. ;иначе, код символа в AL

;-----------------процедура обработки расширенных кодов

EXT_CODE:

INT 21h ;берём II байт

CMP AL,75 ;проверяем на ß (стрелка влево)

JNE C_R ;если не то, тогда следующая проверка

JMP CURSOR_LEFT ;если да, то перейти к процедуре обработки

CURSOR_LEFT:

CMP AL,77 ; проверяем на à (стрелка вправо)

;и т. д.

BIOS: 16h прерывание, функция 0

1-байтный код-символ в AL;

2-байтный код-ASCII0 в AL, № кода - в AH;

за одно прерывание!

Ввод символов с их выводом на экран.

Выдача эха происходит в той позиции, где предварительно установлен курсор, и текст автоматически переносится на следующую строку при достижении конца текущей строки. Буферная память дисплея – длинная строка (все 25 строк дисплея).

Функция 1 прерывания 21h ожидает ввода символа, если буфер пуст, а затем выводит его в текущую позицию курсора. Ctrl_Break обрабатывается, т. е. может выполняться процедура обработки Ctrl_Break. Введённый символ посылается в AL. Для расширенного кода прерывание повторяется. Функция игнорирует «ESC». Клавиша «ЗАБОЙ»(ß) сдвигает курсор на 1 позицию влево, но символ в этой позиции не стирается. «ENTER» вызывает перемещение курсора в первую позицию текущей строки.

;-------------------получение введенного символа

MOV AH,1 ;номер функции

INT 21H ;ожидаем нажатия клавиши

CMP AL,0 ;расширенный код?

JE EXTENDED_CODE ;если да, то на спец. процедуру

;иначе символ находится в AL

;-------------------процедура обработки расширенных кодов

INT 21H ;получаем в AL номер кода

CMP AL,77 ;проверка на "курсор-вправо"

JNE C_R ;если нет, проверка следующего

JMP CURSOR_RIGHT ;если да, то на процедуру

C_R: CMP AL,75 ;... и т. д.

Приём символа без ожидания.

Некоторые программы, работающие в реальном времени, не могут останавливаться и ждать нажатия клавиши, они принимают символ из буфера в те моменты, когда это удобно для программы, например, в игровой программе.

Функция 6 прерывания 21h – это единственный способ получить введённый символ без ожидания. Эта функция не дает эха на экран и не распознает Ctrl-Break. Перед вызовом прерывания в DL должно быть помещено 0FFH. В противном случае функция 6 служит совершенно противоположной цели - печатает в текущей позиции курсора символ, находящийся в DL. Флаг нуля устанавливается в 1, если буфер клавиатуры пуст. Если символ принят, то он помещается в AL.

Код ASCII 0 индицирует расширенный код и для получения номера кода, прерывание должно быть повторено.

MOV AH,6 ;номер функции DOS

MOV DL,0FFH ;запрос ввода с клавиатуры

INT 21H ;получение символа

JZ NO_CHAR ;переход если нет символа

CMP AL,0 ;проверка на расширенный код

JE EXTENDED_CODE ;если да, то на спец. процедуру

... ;иначе в AL код ASCII

EXTENDED_CODE: INT 21H ;получаем номер расширенного кода

... ;номер кода в AL

Получение строки символов.

MS-DOS предоставляет процедуры для приёма строки символов. Сигнал окончания строки – ввод возврата каретки («ENTER»).

Должна быть отведена память, достаточная для приёма строки, и (в общем случае) записывается длина каждой строки для того, чтобы отделить одну строку от другой. Это делается с помощью дескрипторов строки. DOS хранит длину строки прямо в начале самой строки, и для программы достаточно знать положение строки в памяти.

Функция 0Ah прерывания 21h позволяет вводить строку длиной до 254 символов, выдавая эхо на терминал. Эта процедура продолжает ввод символов до тех пор, пока не нажата клавиша возврат каретки. DS:DX указывает на адрес памяти, куда должна быть помещена строка. Первый байт в этой позиции должен содержать число байтов, отводимых для этой строки. После того, как строка введена, второй байт будет содержать количество реально введённых символов. Сама строка начинается с третьего байта. Т. е. нужно отвести память в строке 2-а первых байта для дескрипторов и один последний для возврата каретки («ENTER»).

Код возврата каретки ASCII 13 – вводится как последний символ строки, но он не учитывается в результате, который функция 0Ah помещает во второй байт дескриптора. Таким образом, для получения 50-и символьной строки нужно 53 байта. В первый байт необходимо поместить ASCII 51.После ввода 50 символов второй байт будет содержать ASCII 50, и 53-й байт будет содержать ASCII 13.

;----------резервирование памяти для хранения и обработки данных

STRING DB 53 DUP(?) ;область для строки в 50 символов

;----------получение строки с клавиатуры

LEA DX, STRING ;DS:DX указывает на адрес строки

MOV BX, DX ;пусть BX тоже указывает на строку

MOL AL,51 ;установка длины строки (+1 для CR)

MOV [BX],.AL ;посылаем в первый байт дескриптора

MOV AH,0Ah ;№ функции

INT 21h ;получение строки

MOV AH,[BX]+1 ;теперь количество введённых символов по -

;мещено и в AH.

Можно использовать возможности редактирования строки MS-DOS. Нажатие клавиши «ЗАБОЙ» или «ß» удаляет символ с экрана и из памяти. Расширенные коды игнорируются, допускаются пустые строки (т. е. возврат каретки без символов). На терминале при достижении конца строка переносится на следующую строку, а при достижении правого нижнего угла экран сдвигается на строку вверх. Если вводится больше символов, чем отведено места – функция DOS генерирует гудок через динамик.

Функция 3Fh прерывания 21h – функция общего назначения, чаще используется при дисковых операциях – позволяет получить строку без эха. Она требует определённого дескриптора файла, который является кодовым числом, используемым О. С. для обозначения в/вывода.

Для клавиатуры – дескриптор 0 помещается в BX ; в DS:DX – адрес строки, в CX – max длина строки.

;---------------чтение строки без эха

MOV AH, 3Fh ;№ функции

MOV BX, 0 ;№ дескриптора файла

LEA DX, STRING_BUFFER ;указатель на буфер ввода строки

MOV CX,100 ;max длина строки

INT 21h ;ожидание ввода

* * *

Ввод строки завершается нажатием клавиши возврата каретки и DOS добавляет в конец строки 2-а символа: возврат каретки (ASCII 13) и перевод строки (ASCII 10), т. е. строка может занимать 102 байта. Длина введённой строки возвращается в AX (со значениями символов ограничителей).

Порядок выполнения работы.

1. Разработать программы на языке ассемблер, иллюстрирующие:

а) получение строки символов и выдачи ее на терминал;

б) приём одного символа с клавиатуры и вывода его на

терминал.

2. Получить результат.

3. Составить отчет.

4. Подробно объяснить алгоритм работы программы,

.

Программа должна иметь:

1. Подсказки взаимодействия пользователя с программой.

2. Сообщения, дающие информацию о действиях программы и результатах её работы.

Литература.

1.  Питер Абель “Язык Ассемблера для IBM PC и программирования” / Пер. с англ. . - М.:ВШ,1992.-441с.:ил.

2.  “Программирование на языке Ассемблер для IBM.”