Справочник программиста на персональном компьютере фирмы IBM. Клавиатура - Очистка буфера клавиатуры
ОГЛАВЛЕНИЕ
3.1.1 Очистка буфера клавиатуры.
Программа должна очистить буфер клавиатуры, перед тем, как
выдать запрос на ввод, исключая тем самым посторонние нажатия
клавиш, которые могут к тому времени накопиться в буфере. Буфер
может накапливать до 15 нажатий на клавишу, независимо от того,
являются ли они однобайтными кодами ASCII или двухбайтными расши-
ренными кодами. Таким образом, буфер должен отвести два байта
памяти для каждого нажатия на клавишу. Для однобайтных кодов
первый байт содержит код ASCII, а второй - скан-код клавиши. Для
расширенных кодов первый байт содержит ASCII 0, а второй номер
расширенного кода. Этот код обычно совпадает со скан-кодом клави-
ши, но не всегда, поскольку некоторые клавиши могут комбиниро-
ваться с клавишами сдвига для генерации различных кодов.
Буфер устроен как циклическая очередь, которую называют также
буфером FIFO (первый вошел - первый ушел). Как и любой буфер он
занимает непрерывную область адресов памяти. Однако не имеется
определенной ячейки памяти, которая хранит "начало строки" в
буфере. Вместо этого два указателя хранят позиции головы и хвоста
строки символов, находящейся в буфере в текущий момент. Новые
нажатия клавиш запасаются в позициях, следующих за хвостом (в
более старших адресах памяти) и соответственно обновляется указа-
тель хвоста буфера. После того, как израсходовано все буферное
пространство, новые символы продолжают вставляться, начиная с
самого начала буферной области; поэтому возможны ситуации, когда
голова строки в буфере имеет больший адрес, чем хвост. После того
как буфер заполнен, новые вводимые символы игнорируются, при этом
прерывание клавиатуры выдает гудок через динамик. На рис. 3-2
показаны некоторые возможные конфигурации данных в буфере.
В то время как указатель на голову установлен на первый вве-
денный символ, указатель на хвост установлен на позицию за пос-
ледним введенным символом. Когда оба указателя равны, то буфер
пуст. Чтобы разрешить ввод 15 символов требуется 16-я пустая
позиция, 2 байта которой всегда содержат код возврата каретки
(ASCII 13) и скан-код клавиши <Enter>, равный 28. Эта пустая
позиция непосредственно предшествует голове строки символов. 32
байта буфера начинаются с адреса 0040:001E. Указатели на голову и
хвост расположены по адресам 0040:001A и 0040:001C, соответствен-
но. Хотя под указатели отведено 2 байта, используется только
младший байт. Значения указателей меняются от 30 до 60, что соот-
ветствует позициям в области данных BIOS. Для очистки буфера надо
просто установить значение ячейки 0040:001A равным значению ячей-
ки 0040:001C.
Отметим, что программа имеет возможность вставлять символы в
буфер, завершая строку символом возврата каретки и соответственно
меняя значения указателей. Если это проделать правильным образом
перед завершением программы, то при возврате управления в MS DOS
эти символы будут считаны и может быть автоматически загружена
другая программа.
Низкий уровень.
В Бейсике для получения и изменения значений указателей буфера
используются операторы PEEK и POKE:
100 DEF SEG = &H40 'устанавливаем значение сегмента
110 POKE &H1C, PEEK(&H1A) 'выравниваем указатели
Этот метод не самый лучший. Некоторые программы могут создавать
буфер где-нибудь в другом месте памяти, а кроме того, всегда
существует возможность, что посреди строки 110 произойдет преры-
вание клавиатуры, которое изменит указатель хвоста. По этим при-
чинам лучше оставить указатели буфера в покое. Вместо этого,
лучше читать из буфера до тех пор, пока не будет возвращен символ
ASCII 0, показывающий, что буфер пуст:
100 IF INKEY$<>"" THEN 100 'берем следующее если не нуль
Средний уровень.
Функция 0C прерывания 21H выполняет любую из функций ввода с
клавиатуры 1, 6, 7, 8 и A (описанных в этой главе), но перед этим
чистит буфер клавиатуры. Надо просто поместить номер функции
ввода в AL (в этом примере - 1):
;---очистка буфера перед ожиданием нажатия клавиши
MOV AH,0CH ;выбираем функцию DOS 0CH
MOV AL,1 ;выбираем функцию ввода символа
INT 21H ;чистим буфер, ждем ввода
Низкий уровень.
Как и в примере высокого уровня делаем значение указателя на
хвост равным значению указателя на голову. Для избежания влияния
прерывания клавиатуры запрещаем прерывания на время модификации
указателя:
;---выравниваем значения указателей на голову и хвост
CLI ;запрещаем прерывания
SUB AX,AX ;обнуляем регистр
MOV ES,AX ;добавочный сегмент - с начала памяти
MOV AL,ES:[41AH] ;берем указатель на голову буфера
MOV ES:[41CH],AL ;посылаем его в указатель хвоста
STI ;разрешаем прерывания