
|
;добавочный сегмент - с начала памяти 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$ находится в правильном диапазоне. |