Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

121

Ввод с клавиатуры с помощью функции 3Fh прерывания INT 21h осуществляется точно так же, как и чтение из файла.

Обычно за стандартным устройством ввода (по умолчанию за клавиатурой) закреплен предопределенный дескриптор 0, который нужно поместить в регистр BX.

ВСХ нужно указать число вводимых символов (достаточно указать максимальную длину строки, например, 80 байт). Ввод завершается после нажатия клавиши <Enter>.

Врегистр АХ возвращается число реально введенных байтов, при этом учитываются также два байта (0Ah и 0Dh), поступающие во входной буфер от нажатия клавиши

<Enter>.

Особая ситуация возникает, если попытаться ввести больше символов, чем затребовано функцией 3Fh. В процессе выполнения этой функции все вводимые символы тут же извлекаются из кольцевого буфера ввода и пересылаются в буфер DOS. Обнаружив во входном потоке коды клавиши <Enter>, DOS пересылает из этого буфера в буфер пользователя в программе точно затребованное число символов (естественно, без кодов <Enter>, которые располагаются в конце вводимой строки). Остальные символы остаются в буфере DOS, готовые к вводу. Фактически, если не принять специальных мер к очистке буфера, они поступят в программу при очередном запросе 3Fh, даже если оператор еще не начал вводить очередную порцию данных. Очевидно, что в этом случае будет нарушена синхронизация хода выполнения программы с работой оператора.

Пример:

buff db 80 dup(?) fhandle dw 0

mov ah,3fh mov bx,fhandle

mov dx,offset buff mov cx,8

int 21h

6.3.2. Функции BIOS

00h, 10h, 20h (INT 16h) — прочитать символ с клавиатуры с ожиданием

Входные данные:

AH=00h (83/84-key), 10h (101/102-key), 20h (122-key)

Возвращаемые значения:

AL=ASCII-код символа, 0 или префикс скан-кода

AL=скан-код нажатой клавиши или расширенный ASCII-код

Примечание.

Если нажатой клавише соответствует ASCII-символ, то в AH возвращается код этого символа, а в AL — скан-код клавиши. Если нажатой клавише соответствует расширенный ASCII-код, в AL возвращается префикс скан-кода (например, 0E0h для клавиш дополнительной клавиатуры) или 0, если префикса нет, а в AH — расширенный ASCII-код.

01h, 11h, 21h (INT 16h) — проверка символа

Входные данные:

AH=01h (83/84-key), 11h (101/102-key), 21h (122-key)

Возвращаемые значения:

ZF=1, если буфер пуст

ZF=0, если в буфере присутствует символ, тогда

http://www.sklyaroff.ru

122

AL= ASCII-код символа, 0 или префикс скан-кода

AH=скан-код нажатой клавиши или расширенный ASCII-код

02h, 12h, 22h (INT 16h) — считать состояние клавиатуры

Входные данные:

AH=02h (83/84-key), 12h (101/102-key), 22h (122-key)

Возвращаемые значения:

AL=байт состояния клавиатуры 1

AH=байт состояния клавиатуры 2 (только для функций 12h и 22h)

Флаги состояния клавиатуры 1: бит 0: правая клавиша Shift нажата бит 1: левая клавиша Shift нажата бит 2: клавиша Ctrl нажата

бит 3: клавиша Alt нажата

бит 4: переключатель Scroll Lock включен бит 5: переключатель Num Lock включен бит 6: переключатель Caps Lock включен бит 7: переключатель Insert включен

Байт флагов клавиатуры 1 хранится в области ПЗУ BIOS по адресу 0000:0417h.

Флаги состояния клавиатуры 2: бит 0: правая клавиша Shift нажата бит 1: левая клавиша Shift нажата бит 2: любая из клавиш Ctrl нажата бит 3: любая из клавиш Alt нажата

бит 4: переключатель Scroll Lock включен бит 5: переключатель Num Lock включен бит 6: переключатель Caps Lock включен бит 7: переключатель Insert включен

Байт флагов клавиатуры 1 хранится в области ПЗУ BIOS по адресу 0000:0417h.

В листинге 6.4 показан пример, в котором программа сначала запрашивает нажатие любой клавиши, затем просит нажать клавишу <Y>, затем клавишу <N> или <n>, затем сочетание клавиш <Shift+F2>. Программа не будет продолжать свою работу, пока пользователь не нажмет требуемую клавишу/клавиши. При этом в программе нажатие клавиши <Y> проверяется по ее ASCII-коду, а нажатие <N> или <n> по скан-коду клавиши.

Листинг 6.4. Пример обработки нажатия клавиш (inchar1.asm)

.model tiny

cr

equ

0Dh

lf

equ

0Ah

.code

org 100h

start:

mov

dx,offset str1

http://www.sklyaroff.ru

123

 

call

subrout

 

mov

ah,10h

 

int

16h

 

mov

dx,offset str2

Key_Y:

call

subrout

mov

ah,10h

 

 

int

16h

 

cmp

al,'Y'

 

jne

Key_Y

 

mov

dx,offset str3

Key_Nn:

call

subrout

mov

ah,10h

 

 

int

16h

 

cmp

ah,31h

 

jne

Key_Nn

 

mov

dx,offset str4

 

call

subrout

Key_ShiftF2:

 

 

mov

ah,10h

 

int

16h

 

cmp

al,0

 

jnz

Key_ShiftF2

 

cmp

ah,55h

 

jnz

Key_ShiftF2

 

mov

dx,offset str5

 

call

subrout

 

ret

 

str1

db

"Для продолжения нажмите любую клавишу...",cr,lf,'$'

str2

db

"Для продолжения нажмите клавишу 'Y'",cr,lf,'$'

str3

db

"Для продолжения нажмите клавишу 'N' или 'n'",cr,lf,'$'

str4

db

"Для продолжения нажмите сочетание Shift-F2",cr,lf,'$'

str5

db

"The End!",cr,lf,'$'

subrout PROC

 

 

mov

ah,9

 

int

21h

 

ret

 

subrout ENDP

 

 

end

start

http://www.sklyaroff.ru

124

В листинге 6.4 используются только функции посимвольного ввода, поэтому в листинге 6.5 показана программа, которая использует функцию DOS 0Ah (INT 21h), позволяющая за одну операцию ввести целую строку. Данная программа преобразует латинские буквы строки из нижнего регистра в верхний, и, наоборот — из верхнего регистра в нижний. Для этого просто над каждым ASCII-кодом символа строки выполняется операция XOR на значение 20h. Например, если над ASCII-кодом прописной буквы "F" (46h) выполнить операцию XOR 20h, то будет получен код 66h — это ASCII-код строчной буквы "f". Справедливо и обратное — если над ASCII-кодом строчной буквы "f" (66h) выполнить операцию XOR 20h, то будет получен ASCII-код прописной буквы "F" (46h). Такой простой операцией можно выполнять преобразование латинских букв из строчных в прописные и обратно.

Пример работы программы:

Введите строку для преобразования: Ivan Sklyaroff

Результат: iVAN sKLYAROFF

Листинг 6.5. Пример ввода и преобразования строки (inchar2.asm)

.model tiny

.code

org 100h

start:

 

 

 

mov

dx,offset mess1

 

mov

ah,9

 

 

int

21h

 

 

mov

dx,offset buffer

; считываем строку в буфер

mov

ah,0Ah

 

 

int

21h

 

 

mov

dx,offset crlf

 

 

mov

ah,9

 

 

int

21h

 

 

mov

dx,offset mess2

 

mov

ah,9

 

 

int

21h

 

 

xor

di,di

 

 

xor

cx,cx

 

 

mov

cl,blength

 

 

mov

si,cx

 

; в SI - длина буфера

xor

ax,ax

 

 

next:

 

 

 

mov

bl,byte ptr bcontents[di]

; взять байт из буфера

xor

bl,20h

 

; операция XOR 20h

mov

dl,bl

 

; выводим символ на экран

mov

ah,2

 

 

int

21h

 

 

inc

di

 

; следующий байт в буфере

cmp

di,si

; если счетчик меньше числа символов, то

jb

next

; продолжить