Справочник программиста на персональном компьютере фирмы 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                   ;разрешаем прерывания