4.4.2. Средства BIOS

Так же как и для вывода на экран, BIOS предоставляет больше возможностей по сравнению с DOS для считывания данных и управления клавиатурой. Напри­мер, функциями DOS нельзя определить нажатие комбинаций клавиш типа Ctrl-Alt-Enter или нажатие двух клавиш Shift одновременно, DOS не может определить момент отпускания нажатой клавиши, и наконец, в DOS нет аналога функции С ungetch(), помещающей символ в буфер клавиатуры, как если бы его ввел пользова­тель. Все это можно осуществить, используя различные функции прерывания 16h и операции с байтами состояния клавиатуры.

INT 16h, АН = 0, 10h, 20к. Чтение символа с ожиданием Вход:   АН = 00h (83/84-key), 10h (101/102-key), 20h (122-key) Выход: AL = ASCII-код символа, О или префикс скан-кода

АН = скан-код нажатой клавиши или расширенный ASCII-код

Каждой клавише на клавиатуре соответствует так называемый скан-код (см. при­ложение 1), соответствующий только этой клавише. Этот код посылается клави­атурой при каждом нажатии и отпускании клавиши и обрабатывается BIOS (об­работчиком прерывания INT 9). Прерывание 16Ьдает возможность получить код нажатия, не перехватывая этот обработчик. Если нажатой клавише соответствует ASCII-символ, то в АН возвращается код этого символа, а в AL - скан-код клави­ши. Если нажатой клавише соответствует расширенный ASCII-код, в AL возвра­щается префикс скан-кода (например, OEOh для серых клавиш) или 0, если пре­фикса нет, а в АН - расширенный ASCII-код. Функция OOh обрабатывает только комбинации, использующие клавиши 84-кдавишной клавиатуры; 10h обрабаты­вает все 101-105-клавишныекомбинации; 20h - 122-клавишные. Тип клавиату­ры можно определить с помощью функции 09h прерывания 16h, если она поддер­живается BIOS (поддерживается ли эта функция, можно узнать с помощью

функции OCOh прерывания 15h).

INT 16h,AH= 1, llh,21 к Проверка символа Вход:   АН = Olh (83/84-key), llh (101/102-key), 21h (122-key) Выход: ZF = 1, если буфер пуст

ZF = 0, если в буфере присутствует символ, тогда AL = ASCII-код символа, 0 или префикс скан-кода АН = скан-код нажатой клавиши или расширенный ASCII-код

Символ остается в буфере клавиатуры, хотя некоторые BIOS удаляют символ из буфера при обработке функции ОШ, если он соответствует расширенному ASCII-коду, отсутствующему на 84-клавишных клавиатурах.

INT 16h, AH = 05k Поместить символ в буфер клавиатуры Вход:   АН - 05h

СН = скан-код

CL = ASCII-код Выход: AL = 00, если операция выполнена успешно

AL = Olh, если буфер клавиатуры переполнен

АН модифицируется многими BIOS

Обычно вместо скан-кода в СН можно поместить 0, если функция, которая будет выполнять чтение из буфера, использует именно ASCII-код. Например, следующая программа при запуске из DOS вызывает команду DIR (но при запус­ке из некоторых оболочек, например FAR, этого не произойдет).

ungetch.asm

заносит в буфер клавиатуры завершения программы команду DIR так,   чтобы она выполнилась сразу после

start:

ungetch: .model .code

org

mov call

mov

call

mov

call

mov

mov mov int ret

end tiny lOOh

cl,'d'

ungetch

cl,'i'

ungetch

cl.'r'

ungetch cl.ODh

ah,5

ch,0 16h

start

; СОМ-файл

; С1_ = ЛБСИ-код буквы "д"

; А8С11-код буквы "Г

; ЛБСИ-код буквы "г"

; перевод строки

; АН = номер функции

; СН =0 (скан-код неважен)

; поместить символ в буфер

; завершить программу

INT 16п, АН = 02h, 12h, 22к Считать состояние клавиатуры Вход:   АН - 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 включенаі   Основы программирования для MS DOS

бит 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 соответствующим образом изменит состояние клавиатуры:

nolock.asm

Самая короткая программа для выключения NumLock, CapsLock и ScrollLock. Запускать без параметров.

start:

.model . code

org

mov mov

ret end

tiny

100h

СОМ-файл. AX при

без параметров в всегда равен O.

запуске СОМ-файла командой строке

ds.ax

byte ptr start ds:0417h,al

Так что теперь DS = 0. Байт состояния клавиатуры Выход из программы.

1 = 0.

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

Помимо этих двух байт BIOS хранит в своей области данных и весь клавиа­турный буфер, к которому также можно обращаться напрямую. Буфер занимает 16 слов с 0h:041Ehno Oh:043Dh включительно, причем по адресу 0h:041 Ah лежит адрес (ближний) начала буфера, то есть адрес, по которому располагается следу­ющий введенный символ, а по адресу находится адрес конца буфера, так что если эти два адреса равны, буфер пуст. Буфер действует как кольцо: если на­чало буфера - 043Ch, а конец - то в буфере расположены три символа по адресам 043Ch, Eh и 0420h. Каждый символ хранится в виде слова - того же самого, которое возвращает функция 10h прерывания INT 16h. В некоторых слу­чаях (если) буфер размещается по другим адресам, тогда адрес его начала хранитсяв области данных BIOS по адресу а конца - по адресу Прямой дос-

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

тов ввода-вывода.