1. Средства BIOS
Так же как и для вывода на экран, BIOS предоставляет больше возможностей по сравнению с DOS для считывания данных и управления клавиатурой. Например, функциями DOS нельзя определить нажатие комбинаций клавиш типа Ctrl-Alt-Enter или нажатие двух клавиш Shift одновременно, DOS не может определить момент отпускания нажатой клавиши, и наконец, в DOS нет аналога функции С ungetch (), помещающей символ в буфер клавиатуры, как если бы его ввел пользователь. Все это можно осуществить, используя различные функции прерывания 16h и операции с байтами состояния клавиатуры.
INT 16h, АН = 0, 10h, 20h - Чтение символа с ожиданием
Ввод: | АН = 00h (83/84-key), 10h (101/102-key), 20h (122-key) |
Вывод: | AL = ASCII-код символа, 0 или префикс скан-кода АН = скан-код нажатой клавиши или расширенный ASCII-код |
Каждой клавише на клавиатуре соответствует так называемый скан-код (см. приложение 1), соответствующий только этой клавише. Этот код посылается клавиатурой при каждом нажатии и отпускании клавиши и обрабатывается BIOS (обработчиком прерывания INT 9). Прерывание 16h дает возможность получить код нажатия, не перехватывая, этот обработчик. Если нажатой клавише соответствует ASCII-символ, то в АН возвращается код этого символа, а в AL - скан-код клавиши. Если нажатой клавише соответствует расширенный ASCII-код, в AL возвращается префикс скан-кода (например, Е0 для серых клавиш) или 0, если префикса нет, а в АН - расширенный ASCII-код. Функция 00Н обрабатывает только комбинации, использующие клавиши 84-клавишной клавиатуры, l0h обрабатывает все 101 - 105-клавишные комбинации, 20h - 122-клавишные. Тип клавиатуры можно определить с помощью функции 09h прерывания 16h, если она поддерживается BIOS (поддерживается ли эта функция, можно узнать с помощью функции C0h прерывания 15h).
INT 16h, АН = 1, 11h, 21h - Проверка символа
Ввод: | АН = 01h (83/84-key), 11h (101/102-key), 21h (122-key) |
Вывод: | ZF = 1, если буфер пуст ZF = 0, если в буфере присутствует символ, в этом случае AL = ASCII-код символа, 0 или префикс скан-кода АН = скан-код нажатой клавиши или расширенный ASCII-код |
Символ остается в буфере клавиатуры, хотя некоторые BIOS удаляют символ из буфера при обработке функции 01h, если он соответствует расширенному ASCII-коду, отсутствующему на 84-клавишных клавиатурах.
INT 16h, АН = 05h - Поместить символ в буфер клавиатуры
Ввод: | АН = 05h СН = скан-код CL = ASCII-код |
Вывод: | AL = 00, если операция выполнена успешно AL = 01h, если буфер клавиатуры переполнен АН модифицируется многими BIOS |
Обычно можно поместить 0 вместо скан-кода в СН, если функция, которая будет выполнять чтение из буфера, будет использовать именно ASCII-код.
Например, следующая программа при запуске из DOS вызывает команду DIR (но при запуске из некоторых оболочек, например FAR, этого не произойдет).
Пример №1.1
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov cl,'d' | ; заносим в регистр cl - ASCII-код буквы "d" |
call ungetch | ; переходим на метку ungetch: (вызов подпрограммы) |
mov cl,'i' | ; заносим в регистр cl - ASCII-код буквы "i" |
call ungetch | ; вызываем подпрограмму |
mov cl,'r' | ; заносим в регистр cl - ASCII-код буквы "r" |
call ungetch | ; вызываем подпрограмму |
mov cl,0Dh | ; перевод строки |
Ungetch proc | ; метка начала подпрограммы |
mov ah,05h | ; AH = номер функции |
mov ch,0 | ; CH = 0 (скан-код неважен) |
int 16h | ; вызов DOS (прерывание) |
ret | ; функция DOS "завершить работу процедуры" |
Ungetch endp | ; окончание подпрограммы |
end begin | ; метка окончания кода программы |
Оформление процедур (подпрограмм).
______________
Call ungetch
Ungetch proc
Ungetch endp
______________
Ungetch - название процедуры
Call - вызов подпрограммы
Proc - procedure - процедура
endp - end procedure - конец процедуры
Стоит еще отметить, что из одной подпрограммы можно вызывать другие. Из других - третьи. Чаще всего с целью упрощения программы и, тем самым, уменьшения ее размера программисты используют простую связку команд:
Call метка
метка:
Любой вызов подпрограмм заканчивается возращение в блок кода командой ret (ret - return - возврат).
INT 16h, AH = 02h, 12h, 22h - Считать состояние клавиатуры
Ввод: | АН = 02h (83/84-key), 12h (101/102-key), 22h (122-key) |
Вывод: | AL = байт состояния клавиатуры 1 АН = байт состояния клавиатуры 2 (только для функций 12h и 22h) |
Байт состояния клавиатуры 1 (этот байт всегда расположен в памяти по адресу 0000h: 0417h или 0040h: 0017h):
Бит 7: Ins включена
Бит 6: CapsLock включена
Бит 5: NumLock включена
Бит 4: ScrollLock включена
Бит 3: Alt нажата (любая Alt для функции 02h, часто только левая Alt для 12h/22h)
Бит 2: Ctrl нажата (любая Ctrl)
Бит 1: Левая Shift нажата
Бит 0: Правая Shift нажата
Байт состояния клавиатуры 2 (этот байт всегда расположен в памяти по адресу 0000h: 0418h или 0040h: 0018h):
Бит 7: SysRq нажата
Бит 6: CapsLock нажата
Бит 5: NumLock нажата
Бит 4: ScrollLock нажата
Бит 3: Правая Alt нажата
Бит 2: Правая Ctrl нажата
Бит 1: Левая Alt нажата
Бит 0: Левая Ctrl нажата
Оба этих байта постоянно располагаются в памяти, так что вместо вызова прерывания часто удобнее просто считывать значения напрямую. Более того, в эти байты можно записывать новые значения, и BIOS изменит состояние клавиатуры соответственно:
Помимо этих двух байт BIOS хранит в своей области данных и весь клавиатурный буфер, к которому также можно обращаться напрямую. Буфер занимает 16 слов с 0h: 041Eh no 0h: 043Dh включительно, причем по адресу 0h: 041Ah лежит адрес (ближний) начала буфера, то есть адрес, по которому располагается следующий введенный символ, а по адресу 0h: 041Ch лежит адрес конца буфера, так что если эти два адреса равны, буфер пуст. Буфер действует как кольцо: если начало буфера - 043Ch, а конец - 0420h, то в буфере находятся три символа по адресам 043Ch, 041Eh и 0420h. Каждый символ хранится в виде слова - того же самого, которое возвращает функция 10h прерывания INT 16h. В некоторых случаях (если) буфер размещается по другим адресам, тогда адрес его начала хранится в области данных BIOS по адресу 0480h, а конца - по адресу 0482h. Прямой доступ к буферу клавиатуры лишь немногим быстрее, чем вызов соответствующих функций BIOS, и для приложений, требующих максимальной скорости, таких как игры или демо-программы, используют управление клавиатурой на уровне портов ввода-вывода.
0 комментариев