![]()
Главная Обратная связь Дисциплины:
Архитектура (936) ![]()
|
Анализ и преобразование скэн-кода
Действия BIOS ISR при нажатии и отпускании одной и той же клавиши различны. Клавиши в зависимости от алгоритма обработки их скэн-кода можно разделить на: 1. шифт-клавиши (Right-Shift, Left-Shift, Alt, Ctrl); 2. триггерные клавиши (NumLock, ScrollLock, CapsLock); 3. клавиши с буферизацией расширенного кода; 4. специальные клавиши (клавиша PrnScr, комбинация Alt-Ctrl-Del, комбинация Ctrl-C (Ctrl-Break)). За каждой шифт- или триггерной клавишей закреплен свой бит в ячейках памяти по адресам 40: 17h и 40: 18h (табл. 3.1). При каждом нажатии или отпускании шифт-клавиши ISR BIOS инвертирует соответствующий бит. Таким образом, текущее состояние бита шифт-клавиши говорит о том, нажата она в данный момент или отпущена. За триггерными клавишами закреплены два бита: один из них инвертируется только при нажатии клавиши ("фиксирует" состояние "Вкл/Выкл"), другой - при нажатии и отпускании, отслеживая текущее состояние клавиши. Текущее состояние шифт- и тригтерных клавиш используется BIOS-обработчиком прерывания от клавиатуры при определении правил преобразования скэн-кодов от других клавиш. Большинство клавиш и их комбинаций с шифт-клавишами - это клавиши с буферизацией расширенного кода: при их нажатии в специальный буфер памяти помещается двухбайтовый код, называемый BIOS-кодом клавиши. Младший байт этого кода равен ASCII-коду символа, либо нулю. Старший байт равен скэн-коду клавиатуры, либо так называемому расширенному скэн-коду. Комбинация "ASCII-код/ скэн-код клавиатуры" генерируется в следующих случаях:
Табл. 3.1. Состояние шифт- и триггерных клавиш
Двухбайтовый BIOS-код вида “0 / расширенный скэн-код” генерируется и записывается в буфер клавиатуры при нажатии клавиш Fl - F12, Ins, Del, клавиш управления курсором Home, Up, PgUp, Left, Right, End, Down, PgDn и их комбинации с клавишами Alt, Ctrl, Shift, а также при нажатии комбинации Alt-ASCII-клавиша. Значение расширенного скэн-кода определяется технической документацией BIOS. Правила BIOS таковы, что расширенный скэн-код и скэн-код от клавиатуры не совпадают. Некоторые нажатия клавиш обрабатываются ISR BIOS особым образом. К их числу относятся: 1) клавиша PrnScr, при нажатии которой ISR BIOS выполняет программное прерывание 5; 2) комбинация Alt-Ctrl-Dei, обнаружив такую комбинацию, ISR BIOS передает управление программе начальной загрузки. Эта программа также входит в состав BIOS; 3) комбинация Ctrl-C (Ctrl-Break); ISR BIOS записывает по абсолютному адресу памяти 00471h значение 80h. Оно используется как флаг, сигнализирующий о желании пользователя остановить выполнение текущей программы. Значение этого флага проверяют при своем выполнении функции MS-DOS, работающие с файлами stdin, stdout, stdprn и stdaux. Буфер клавиатуры
Буфер BIOS для записи кодов клавиш занимает 32 байта памяти с адреса 40:lEh до 40:3Eh. Запись информации в буфер выполняет ISR BIOS прерывания 9, чтение - функции ISR BIOS прерывания 16h. Буфер клавиатуры рассчитан на 15 нажатий клавиш, генерирующих двухбайтовые коды и поэтому имеет 30 байт для кодов клавиш и еще два "холостых" дополнительных байта, которые резервируются под двухбайтовый код для клавиши ENTER. Буфер организуется как кольцевая очередь, доступ к которой осуществляется с помощью указателя «головы» (head pointer), адрес которого 40:1Ah, и указателя «хвоста» (tail pointer), адрес которого 40:1Ch. Указатель "хвоста" задает смещение до слова, где будет записан обработчиком прерывания 9 код буферизуемой клавиши, т.е. первое свободное слово буфера. Указатель "головы" задает смещение слова, которое будет возвращено запросу буферизованного ввода с клавиатуры, сделанного операционной системой или BIOSoм. При каждом нажатии клавиши, для которой генерируется двухбайтовый код, ISR BIOS прерывания 9,'используя текущее значение указателя "хвоста", записывает в память образованный двухбайтовый код. После этого указатель "хвоста" увеличивается на 2. Если указатель "хвоста" перед доступом к буферу указывает на верхнюю границу буфера (на слово 40:3Eh), указатель после записи в буфер "перепрыгивает" на начало буфера, т.е. ему присваивается значение 40:1Eh. Поэтому значение указателя "хвоста" может быть и меньше значения указателя "головы". Это значит, что указатель "хвоста" "перескочил" назад к нижней границе буфера. Когда указатель "хвоста" догонит указатель "головы", наступит переполнение буфера. В этом случае указатель "хвоста" задает смещение до "холостой" позиции. Каждое новое нажатие клавиши игнорируется BIOS-обработчиком; код клавиши не помещается в буфер, и звучит сигнал динамика. Указатель "головы" используется BIOS-обработчиком прерывания 16h, которое вызывается непосредственно из прикладной программы или функциями MS-DOS ввода с клавиатуры. Если выполняется чтение буфера с разрушением информации (функция АН = 0 прерывания 16h, ISR читает два байта памяти по адресу, смещение которого задает указатель "головы", а сегмент равен 40h. Затем ISR прерывания 16h увеличивает (продвигает) указатель "головы" на 2. Если значения указателей "головы" и "хвоста" равны между собой, буфер пуст. В этом случае ISR прерывания 16 выполняет бесконечный цикл ожидания, условием выхода из которого будет неравенство указателей. При нажатии клавиши, генерирующей двухбайтовый код, этот цикл будет прерван BIOS-обработчиком прерывания 9. В результате указатель "головы" продвинется на 2. После завершения ISR BIOS прерывания 9 возобновится выполнение ISR BIOS прерывания 16h. Так как буфер уже не пуст, произойдет выход из цикла и передача в точку вызова прочитанного в буфере двухбайтового кода. Если выполняется чтение буфера без разрушения информации (функция АН = 1 прерывания 16h), продвижение указателя "головы" не происходит, но прочитанный по этому указателю код передается в точку вызова, если только буфер не пуст. Если буфер пуст, ISR прерывания 16h не выполняет цикл ожидания. Вместо этого флаг переноса CF устанавливается в 1, и обработчик завершает свою работу.
На рис. 3.1. приведены примеры пустого буфера клавиатуры и буфера после ввода с клавиатуры строки "TEST", нажатия клавиш Left и F1 при условии, что текущая программа не выполняла в этот момент ввод с клавиатуры. Рис. 3.1. Организация буфера клавиатуры: а - пустой буфер (значения указателей "готовы" и "хвоста" равны); б- тот же буфер после набора на клавиатуре строки TEST, нажатия специальных клавиш Left и F1 (текущая программа не выполняет ввод информации и указатель "головы" не продвигается)
Буфер клавиатуры - это классический пример использования кольцевого буфера для организации асинхронного взаимодействия двух программ по схеме "производитель-потребитель". Одна из программ (ISR BIOS прерывания 9) "производит" информацию или, как говорят, является процессом-производителем. Исполняемая программа через функцию АН= 00h прерывания 16h BIOS "потребляет" информацию или является процессом-потребителем. Асинхронность взаимодействия означает, что запись в буфер новой информации и чтение из него происходят в случайные, не связанные между собой моменты времени. Так как производитель постоянно анализирует наличие переполнения буфера, не происходит переопределения не прочитанных еще потребителем кодов клавиатуры. Другими словами, при переполнении буфера производитель блокируется до тех пор, пока потребитель не прочитает одно или несколько слов из буфера. Если же буфер пуст и выполняется попытка чтения информации, функция АН = 00h прерывания 16h BIOS переходит к бесконечному циклу, условием которого является неравенство между собой указателей "головы" и "хвоста". Фактически текущая программа, выполняющая ввод с клавиатуры, блокируется, не давая "потребить" несуществующую еще информацию.
![]() |