Алгоритм ввода данных с клавиатуры
Клавиатура персонального компьютера - одно из важнейших его внешних устройств, предназначенное для кодирования и ввода буквенно-цифровой и управляющей информации.
Клавиатура является программно-управляемым устройством и имеет в своем составе специализированный контроллер (однокристальную микроЭВМ), основной функцией которого является отслеживание фактов нажатия и отпускания клавиш путем циклического сканирования наборного поля. Сканирование производится с периодичностью 10 раз в секунду, в каждом цикле формируется скан-код нажатой (или отпущенной) клавиши, который временно сохраняется во внутреннем буфере контроллера и затем передается в соответствующий порт ввода-вывода, доступный прикладным программам.
Скан-код - это уникальный однобайтовый номер, присваиваемый каждой клавише[10]. Семь младших битов скан-кода – это собственно код клавиши, а старший бит используется для кодирования факта её нажатия (0) или отпускания (1). Такая система позволяет закодировать 128 различных клавиш (коды с "0" по "127" при нажатии и с "128" по "255" - при отпускании), что превышает потребности стандартной 101-клавишной клавиатуры.
Клавиатура подключена к линии IRQ1 контроллера прерываний, которой соответствует прерывание №9, и к порту ввода-вывода с адресом 60h, в который помещается скан-код последней нажатой (или отпущенной) клавиши. В процессе обмена данными с клавиатурой участвует также порт 61h, доступный как для чтения, так и для записи. Запись "1" в старший бит этого порта блокирует обмен данными с клавиатурой.
Дальнейшая реализация процесса ввода данных осуществляется программным обработчиком клавиатурного прерывания, который читает принятый в порт 60h скан-код клавиши, анализирует его значение и формирует соответствующие информационные структуры в области данных BIOS (таблица 2.3).
Таблица 2.3 - Блок данных BIOS, обслуживающий ввод с клавиатуры
Начальный адрес (hex) | Длина, байт | Назначение |
0040:0017 | Флаги клавиатуры | |
0040:0019 | Текущее (накопленное) значение вводимого ASCII-кода символа (Alt + цифра) | |
0040:001A | Адрес "хвоста" буфера клавиатуры | |
0040:001C | Адрес "головы " буфера клавиатуры | |
0040:001E | 20h | Буфер клавиатуры (16 двухбайтовых элементов) |
Флаги клавиатуры
Эти два байта в области данных BIOS формируются обработчиком прерывания №9 при нажатии и отпускании управляющих клавиш и клавиш-переключателей. Определенные биты этих флаговых байтов устанавливаются в "1" или "0" в зависимости от текущего состояния соответствующих клавиш или же от того, установлен или нет соответствующий режим.
Например, при нажатии клавиши <CapsLock> 6-й бит первого и второго флаговых байтов будет установлен в "1". При отпускании этой клавиши 6-й бит второго байта будет обнулен, а первый байт останется без изменений, что соответствует ситуации "установлен верхний регистр". После повторного нажатия и отпускания этой клавиши оба флаговых бита вернутся в исходное (нулевое) состояние.
В приведенных ниже диаграммах показана информационная структура флагов клавиатуры.
= 1: Нажата правая клавиша <Shift> | ||||||||||||||||
= 1: Нажата левая клавиша <Shift> | ||||||||||||||||
= 1: Нажата клавиша <Ctrl> | ||||||||||||||||
= 1: Нажата клавиша <Alt> | ||||||||||||||||
= 1: Установлен режим "ScrollLock" | ||||||||||||||||
= 1: Установлен режим "NumLock" | ||||||||||||||||
= 1: Установлен режим "CapsLock" | ||||||||||||||||
= 1: Установлен режим "Insert" | ||||||||||||||||
Рисунок 2.2 Структура 1-го "флагового" байта (0040:0017)
= 1: Нажата правая клавиша < Ctrl > | ||||||||||||||||
= 1: Нажата левая клавиша < Alt > | ||||||||||||||||
= 1: Нажата клавиша < SysReq > | ||||||||||||||||
= 1: Установлен режим " Pause " | ||||||||||||||||
= 1: Нажата клавиша <ScrollLock> | ||||||||||||||||
= 1: Нажата клавиша <NumLock> | ||||||||||||||||
= 1: Нажата клавиша <CapsLock> | ||||||||||||||||
= 1: Нажата клавиша <Insert> | ||||||||||||||||
Рисунок 2.3 Структура 2-го "флагового" байта (0040:0018)
Буфер клавиатуры
Буфер клавиатуры - это линейная область ОЗУ, в которую программа-обработчик прерывания №9 записывает данные об очередной нажатой символьной клавише, а прикладные программы считывают эти данные для дальнейшего использования. Для каждого нажатия клавиши в буфере зарезервировано по два байта: один (младший) байт для скан-кода клавиши, другой (старший байт) - для ASCII-кода символа, соответствующего этой клавише.
В первых PC/XT поддерживался буфер клавиатуры фиксированной длины 32 байта, который располагался в диапазоне адресов с 0040:001Eh по 0040:003Eh. Такой буфер рассчитан на регистрацию 16 последовательных нажатий клавиш.
В PC/AT адрес начала буфера (смещение относительно сегмента 0040h) указан в ячейке 0000:0480h, а адрес конца буфера - в ячейке 0000:0482h. Обычно эти ячейки содержат значения соответственно 001Eh и 003Eh, при этом размер и расположение буфера клавиатуры PC/AT аналогичны PC/XT.
При нажатии символьной клавиши обработчик прерывания вычисляет значение кода ASCII по ее скан-коду (с учетом текущего состояния флагов клавиатуры) и записывает эти коды в два соседних байта буфера.
Процесс записи данных в буфер клавиатуры и чтения данных из буфера регулируется двумя указателями. Двухбайтовое слово по адресу 0040:001Сh содержит адрес (смещение относительно сегмента 0040h) "головы" буфера, то есть указывает обработчику прерывания, куда следует записать пару кодов очередной нажатой клавиши, а двухбайтовое слово по адресу 0040:001Аh содержит адрес "хвоста" буфера, то есть указывает прикладной программе, откуда следует прочитать пару кодов первой из еще не прочитанных клавиш.
В исходном состоянии значения этих указателей одинаковы и равны 001Eh. После завершения каждой операции записи данных в буфер программа-обработчик 9-го прерывания инкрементирует (увеличивает на два) значение "головы", а программа, читающая буфер, соответственно инкрементирует значение "хвоста", – таким образом, при вводе данных с клавиатуры хвост буфера постоянно "догоняет" голову. Буфер клавиатуры организован циклически, то есть при достижении соответствующим указателем конца буфера этот указатель программно устанавливается в начало буфера.
Если прочитаны все записанные в буфер данные – указатели головы и хвоста совпадают, что является признаком "пустого" буфера. Буфер клавиатуры может оказаться "переполненным" – такая ситуация создается в случае, если прикладная программа не прочитала данные из буфера о 16 последних нажатых клавишах, и, следовательно, хвост "отстает" от головы на длину буфера (с учетом его циклической организации). Попытка ввода данных об очередной нажатой клавише в переполненный буфер будет заблокирована.
При прямом вводе кода символа пользователь, удерживая нажатой клавишу <Alt>, набирает ASCII-код символа (в десятичной системе счисления) на дополнительной цифровой клавиатуре. При этом обработчик 9-го прерывания последовательно суммирует вводимый пользователем код (с учетом разряда числа) и сохраняет промежуточные результаты суммирования в ячейке 0040:0019h, пока клавиша <Alt> остается нажатой. После отпускания клавиши <Alt> результат суммирования переписывается из ячейки 0040:0019h в буфер клавиатуры, а сама эта ячейка обнуляется. Естественно, в этом случае соответствующий байт скан-кода в буфере клавиатуры остается нулевым.
Факты нажатия управляющих клавиш <Shift>, <Ctrl>, <Alt>, <ScrollLock>, <NumLock>, CapsLock>, <SysReq> или <Pause>, а также факты отпускания любой клавиши никак не отражаются на состоянии буфера клавиатуры. При нажатии других "несимвольных" клавиш в буфер попадает только скан-код, а байт кода символа остается нулевым.
Учебные задания
Методические указания
Установите режим "командная строка" (сеанс MS DOS).
Загрузите программы Calc.com, Peek.com и Help.exe (в указанном порядке).
Найдите в электронном справочнике Help разделы, описывающие ASCII-коды символов и Scan-коды клавиш. Ознакомьтесь с содержимым указанных разделов.
Не "закрывая" программы Help, активизируйте программу Peek (тройным нажатием левой клавиши <Alt>) и приступайте к выполнению учебных заданий.
В любой момент Вы сможете переключиться на работу с программой Help, нажав клавишу <Esc>, и затем вновь активизировать программу Peek тройным нажатием клавиши <Alt>.
Задание 1.Исследуйте процесс изменения состояния "флаговых" байтов в процессе манипулирования управляющими клавишами Shift, Ctrl, Alt, CapsLock, NumLock. По результатам эксперимента составьте таблицы, аналогичные приведенным на рисунках 1 и 2. Результаты представьте в шестнадцатеричном и двоичном форматах.
Задание 2.Установите режим "верхний регистр", не нажимая клавиши <CapsLock>. Попытайтесь отменить установленный режим с помощью этой клавиши. Проведите аналогичный эксперимент с клавишей <NumLock>. Прокомментируйте результаты эксперимента.
Задание 3.Определите расположение буфера клавиатуры и указателей на его "голову" и "хвост" в адресном пространстве Вашего компьютера. Запишите текущее состояние этих указателей в шестнадцатеричной системе счисления. Запишите адреса (в сегментной форме) "ячеек" буфера клавиатуры, в которые будут записаны и из которых будут прочитаны Scan-код и ASCII-код очередной символьной клавиши.
Задание 4.Введите символы "G", "g", "П" и "п". Определите состояние указателей головы и хвоста буфера клавиатуры после каждого нажатия на клавишу. Определите ASCII-коды введенных символов и Scan-коды соответствующих клавиш. Результаты представьте в шестнадцатеричной, десятичной и двоичной системах счисления. Выполните аналогичные действия для другой символьной клавиши.
Задание 5.Введите символы, указанные в предыдущем задании, прямым набором их ASCII-кодов при нажатой клавише <Alt>. Зафиксируйте промежуточные состояния ячейки с адресом 0040:0019h после ввода каждой очередной цифры ASCII-кода символа, а также состояние этой ячейки и соответствующих ячеек буфера клавиатуры после отпускания клавиши <Alt>. Прокомментируйте результаты.
Задание 6.Введите прямым набором символ с ASCII-кодом "1234". Прокомментируйте результат ввода.
Задание 7.Введите прямым набором "управляющие символы" (ASCII-коды от 0 до 31). Используя электронный справочник HELP, определите комбинации клавиш (Ctrl+клавиша), используемых для ввода управляющих символов.
Задание 8.Используя электронный справочник HELP и технологию прямого набора кодов символов, составьте таблицу ASCII-кодов символов русского алфавита и символов псевдографики.
Контрольные вопросы
Каковы основные функции контроллера клавиатуры ?
Какие манипуляции с клавишами не приводят к изменению состояния буфера клавиатуры ?
В каких случаях значения указателей "головы" и "хвоста" буфера клавиатуры совпадают ?
Как может возникнуть ситуация "переполнение буфера клавиатуры"? Какова реакция компьютера на такую ситуацию ?
Контрольная работа №2
Задача 2.1.Объясните понятия "линейный адрес" и "сегментный адрес". Опишите алгоритм работы сумматора адреса.
Задача 2.2.Определите линейные и сегментные адреса по данным приведенной ниже таблицы. Результаты представьте в шестнадцатеричной и двоичной системах счисления. Определите функциональное назначение соответствующих областей памяти ПК.
Линейный адрес | Сегментный адрес | Область памяти |
0000:010Ch | ||
00462h | ||
0040:0002h | ||
0041Ah | ||
B800:00CDh |
Задача 2.3.Опишите алгоритм работы программы обработки прерывания №9 при нажатии на любую из символьных клавиш.
Задача 2.4.Опишите алгоритм работы программы обработки прерывания №9 при нажатии на любую из управляющих клавиш.
Задача 2.5.(*) Напишите программу для определения SCAN-кодов символьных клавиш и ASCII-кодов соответствующих им символов (используйте средства прямого доступа к порту №60h и буферу клавиатуры).
ВИДЕОСИСТЕМА ПК