Справочник программиста на персональном компьютере фирмы IBM. Клавиатура
Страница 2. Очистка буфера клавиатуры


     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                   ;разрешаем прерывания

 
« Предыдущая статья   Следующая статья »