Компьютер - электронное устройство, которое не заменит человека до тех пор, пока не научится смеяться шуткам начальника и сваливать свои собственные ошибки на соседний компьютер.




;добавочный сегмент - с начала памяти
      MOV AL,ES:[41AH] ;берем указатель на голову буфера
      MOV ES:[41CH],AL ;посылаем его в указатель хвоста
      STI ;разрешаем прерывания


3.1.2 Проверка символов в буфере.



      Вы можете проверить был ли ввод с клавиатуры, не удаляя символ из буфера клавиатуры. Буфер использует два указателя, которые отмечают голову и хвост очереди символов, находящихся в буфере в текущий момент. Когда значения этих указателей равны, то буфер пуст. Надо просто сравнить содержимое ячеек памяти 0040:001A и 0040:001C. (Нельзя просто проверить символ, находящийся в голове очереди, поскольку буфер организован в виде циклической очереди и позиция ее головы постоянно меняется [3.1.1].)

      Высокий уровень.

      Надо просто использовать оператор PEEK для получения значений, а затем сравнить их:
100 DEF SEG = &H40 'устанавливаем сегмент на начало памяти 110 IF PEEK(&H1A)<>PEEK(&H1C) THEN ... '...то буфер не пуст

      Средний уровень.

      Функция 0BH прерывания 21H возвращает значение 0FFH в регистре AL, когда буфер клавиатуры содержит один или более символов и значение 0, когда буфер пуст:
;---проверка наличия символа в буфере
      MOV AH,0BH ;номер функции
      INT 21H ;вызываем прерывание 21H
      CMP AL,0FFH ;сравниваем с 0FFH
      JE GET_KEYSTROKE ;переход если буфер не пуст

      Функция 1 прерывания BIOS 16H предоставляет ту же возможность, но, кроме того, показывает какой символ в буфере. Флаг нуля (ZF) сбрасывается, если буфер пуст, и устанавливается, если в буфере имеется символ. В последнем случае копия символа, находящегося в голове буфера, помещается в AX, но символ из буфера не удаляется. В AL возвращается код символа для однобайтных символов ASCII, иначе ASCII 0 для расширенных кодов, и тогда номер кода - в AH.
;---проверяем наличие символа в буфере
      MOV AH,1 ;номер функции
      INT 16H ;проверка наличия символа
      JZ NO_CHARACTER ;переход если ZF = 1 ;---имеется символ - смотрим какой
      CMP AL,0 ;это расширенный код?
      JE EXTENDED_CODE ;если да, то на другую ветку

      Низкий уровень.

      Как и в примере высокого уровня просто сравниваем указатели:
;---сравниваем указатели на голову и хвост
      MOV AX,0 ;устанавливаем добавочный сегмент
      MOV ES,AX ;на начало памяти
      MOV AL,ES:[41AH] ;берем один указатель
      MOV AH,ES:[41CH] ;берем другой указатель
      CMP AH,AL ;сравниваем их
      JNE GET_KEYSTROKE ;если неравны, то к процедуре ввода


3.1.3 Ожидать ввод символа и не выводить его на экран.



      Обычно вводимые символы выводятся на экран, чтобы было видно, что напечатано. Но иногда автоматическое эхо на экране нежела- тельно. Например, выбор пункта меню по нажатию клавиши. Иногда надо сначала проверить вводимые символы на ошибку перед выводом на экран. В частности, любая программа, обрабатывающая расширен- ные коды, должна избегать автоматического эха, так как при этом первый байт этих кодов (ASCII 0) будет выводиться на экран, вставляя пробелы между символами.

      Высокий уровень.

      Функция Бейсика INKEY$ не дает эхо на терминал. Она возвращает строку длиной 1 байт для символов ASCII и длиной 2 байта для расширенных кодов. INKEY$ не ожидает нажатия клавиши, до тех пор, пока она не помещена в цикл, в котором ожидается нажатие клавиши. Цикл работает, обращаясь к INKEY$, а затем присваивая возвращае- мую им строку переменной, в данном случае C$. Если клавиша не была нажата, то INKEY$ возвращает нулевую строку, т.е. строку длиной ноль символов, которая обозначается двумя знаками кавычек, между которыми ничего нет (""). До тех пор пока INKEY$ возвращает "" - цикл повторяется: 100 C$=INKEY$:IF C$="" THEN 100.
      В нижеприведенном примере предполагается, что вводимые символы выбирают одну из возможностей меню и каждый выбор приводит к выполнению определенной процедуры программы. Выбор может быть сделан за счет нажатия клавиш A, B, C ... (давая 1-байтные коды ASCII) или Alt-A, Alt-B, Alt-C ... (давая 2-байтные расширенные коды). Для их распознавания используется функция LEN, которая определяет была ли строка длиной в 1 или 2 байта. В случае кодов ASCII набор операторов IF...THEN сразу начинает проверять какая клавиша была нажата, отсылая программу на соответствующую проце- дуру. В случае 2-байтных кодов управление передается отдельной процедуре. В этой процедуре функция RIGHT$ убирает левый символ, который просто равен нулю и только отмечает расширенный код. Затем используется функция ASC для преобразования строки из сим- вольной формы в числовую. И, наконец, вторая серия операторов IF...THEN проверяет получившееся число на соответствующие Alt-A, Alt-B и т.д.
100 C$ = INKEY$:IF C$="" THEN 100 'ожидаем нажатия клавиши 110 IF LEN(C$)=2 THEN 500 'если расш. код - на 500 120 IF C$="a" OR C$="A" THEN GOSUB 1100 'это A? 130 IF C$="b" OR C$="B" THEN GOSUB 1200 'это B? 140 IF C$="c" OR C$="C" THEN GOSUB 1300 'это C?
      .
      . 500 C$=RIGHT$(C$,1) 'получаем второй байт расш. кода 510 C=ASC(C$) 'преобразуем его в число 520 IF C=30 THEN GOSUB 2100 'это Alt-A? 530 IF C=48 THEN GOSUB 2200 'Alt-B? 540 IF C=46 THEN GOSUB 2300 'Alt-C?

Отметим, что в строке 120 (и последующих) можно также использо- вать числовые значения кодов ASCII:
120 IF C=97 OR C=65 THEN GOSUB 1100
Конечно надо сначала преобразовать C$ в форму целого числа, как это сделано в строке 510. В программах, в которых требуется длин- ная цепочка таких операторов, можно сэкономить место, изменяя C таким образом, чтобы она всегда соответствовала либо верхнему, либо нижнему регистру. Сначала нужно только проверить, что код ASCII C$ находится в правильном диапазоне.