1. 预备知识
-
前面介绍了使用 9 号中断处理键盘输入,一般的键盘输入,在 CPU 执行完该中断例程后都放在键盘缓冲区中。键盘缓冲区有 16 个字单元,可以存储 15 个按键的扫描码和对应的 ASCII 码。
-
int 16h 中断例程中包含的一个重要功能是从键盘缓冲区中读取一个输入,并将其从缓冲区中删除;如果键盘缓冲区没有内容,则循环等待,该功能的编号为 0。
mov ah,0
int 16h
;调用中断例程后,(ah)=扫描码、(al)=ASCII码
2. 实验任务 1:键盘控制字符颜色
编程,接受用户的键盘输入,输入 r 将屏幕上的字符设置为红色;输入 g 将屏幕上的字符设置为绿色;输入 b 将屏幕上的字符设置为蓝色。
2.1 实验分析
基于 int 16h 中断的 0 号功能从键盘读取输入,并根据扫描码判断当前输入内容,如果是执行内容则设置相应的颜色,否则直接退出程序。
cmp al,'r'
je red
cmp al,'g'
je green
cmp al,'b'
je blue
jmp short sret
在字符属性表中,RGB 分别对应最后三位,则可以通过移位运算改变待使用的颜色值:
mov ah,1
...
red: ;移动一位AH,对应于G
shl ah,1
green: ;移动两位AH,对应于R
shl ah,1
blue: ;不移动AH,对应于B
...
整体代码为:
assume cs:code
code segment
start:
mov ah,0
int 16h
;调用16h中断例程的0号功能从键盘缓冲区读取数据,如果为空则循环等待
mov ah,1
;最后三位依次为RGB
cmp al,'r'
je red
cmp al,'g'
je green
cmp al,'b'
je blue
jmp short sret
red: ;移动一位AH,对应于G
shl ah,1
green: ;移动两位AH,对应于R
shl ah,1
blue: ;不移动AH,对应于B
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
s:
and byte ptr es:[bx],11111000b
or es:[bx],ah
add bx,2
loop s
sret:
mov ax,4c00h
int 21h
code ends
end start
2.2 实验结果
r:
g:
b:
3. 实验任务 2:字符串输入
编程,完成字符串输入程序,包含以下功能:(1)在输入的同时显示这个字符串;(2)在输入回车后,字符串输入结束;(3)删除已经输入的字符。
3.1 实验分析
3.1.1 整体子程序功能设计
;(ah)=功能号,0 表示入栈、1 表示出栈、2 表示显示
;ds:si 指向字符栈空间
;对于 0 号功能,(al)=入栈字符
;对于 1 号功能,(al)=栈中返回的字符
;对于 2 号功能,(dh)、(dl)=字符串在屏幕上显示的行和列
charstack:
jmp short charstart ;用于显示字符串
table dw charpush,charpop,charshow
3.1.2 字符串的输入和删除
每个新输入的字符存储在原字符之后,而删除从字符串的末尾进行。字符串的插入和删除类似于栈后进先出的性质,因此考虑使用栈管理字符串的存储空间。基于子程序 charpush 将输入字符压入字符栈:
charpush:
mov bx,top
mov [si][bx],al ;压入字符
inc top ;移动栈顶指针
基于子程序 charpop 从字符栈中删除字符:
charpop:
cmp top,0
je sret ;栈为空
dec top
mov bx,top
mov al,[si][bx] ;出栈并赋值给AL
3.1.3 输入回车结束字符串输入
输入回车后,在字符串的末尾加入 0 表示输入结束。子程序 enter_k 用于完成在字符串的结尾插入空格,并结束字符串的输入:
enter_k:
mov al,0 ;空格的ASCII码,后续用于标识字符串结尾
mov ah,0
call charstack
mov ah,2
call charstack ;入栈空格并显示
3.1.4 输入的同时显示字符串
每次在输入或删除字符时,以栈底到栈顶的顺序显示所有字符。在输入字符时,结合 0 号功能和 2 号功能实现在输入字符时显示字符串:
getstrs:
mov ah,0
int 16h ;从键盘缓冲区读取字符,(ah)=扫描码、(al)=ASCII码
mov ah,0
call charstack
mov ah,2
call charstack ;入栈字符并显示
在删除字符时,结合 1 号功能和 2 号功能实现在删除字符串时显示字符串:
backspace_k:
mov ah,1
call charstack
mov ah,2
call charstack ;出栈并显示
3.1.5 子程序 charstart
上述子程序通过功能号和 charstack 完成相应的功能。在 charstack 中,首先调用 charstart 中,通过功能号确定相应子程序的入口地址。
charstart:
cmp ah,2 ;0表示入栈,1表示出栈,2表示显示
ja sret ;大于2时直接退出
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr table[bx] ;根据偏移跳转到对应子程序
3.1.6 字符串的显示
2 号功能显示字符串,基于 charshows 和 noemtpy 显示字符串:
charshows:
cmp bx,top
jne noempty
mov byte ptr es:[di],' '
;字符以\0结尾
jmp sret
noempty:
mov al,[si][bx]
mov es:[di],al ;显示字符
inc bx
add di,2 ;偏移2个字节写字符
jmp charshows ;显示字符串
3.1.7 整体设计
综合以上子程序的内容以及加上某些特殊处理,整体代码执行流程可用以下流程图表示:
整体代码:
;子程序:字符栈的入栈、出栈和显示
;参数说明:(ah)=功能号,0表示入栈,1表示出栈,2表示显示
;ds:si指向字符栈空间
;对于0号功能,(al)=入栈字符
;对于1号功能,(al)=返回的字符
;对于2号功能,(dh)、(dl)=字符串在屏幕上显示的行和列
assume cs:code
code segment
start:
call getstr
mov ax,4c00h
int 21h
getstr:
push ax
getstrs:
mov ah,0
int 16h ;从键盘缓冲区读取字符,(ah)=扫描码、(al)=ASCII码
cmp al,20h
jb nochar ;ASCII码小于20h时不为字符
mov ah,0
call charstack
mov ah,2
call charstack ;入栈字符并显示
jmp getstrs
nochar:
cmp ah,0eh ;按下退格键
je backspace_k
cmp ah,1ch ;按下回车键
je enter_k
jmp getstrs
backspace_k:
mov ah,1
call charstack
mov ah,2
call charstack ;出栈并显示
jmp getstrs
enter_k:
mov al,0 ;空格的ASCII码,后续用于标识字符串结尾
mov ah,0
call charstack
mov ah,2
call charstack ;入栈空格并显示
pop ax
ret
charstack:
jmp short charstart
table dw charpush,charpop,charshow
top dw 0
charstart:
push bx
push dx
push di
push es
cmp ah,2 ;0表示入栈,1表示出栈,2表示显示
ja sret ;大于2时直接退出
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr table[bx]
;根据偏移找到对应子程序的偏移地址
charpush:
mov bx,top
mov [si][bx],al ;压入字符
inc top ;移动栈顶指针
jmp sret
charpop:
cmp top,0
je sret ;栈为空
dec top
mov bx,top
mov al,[si][bx] ;出栈并赋值给AL
jmp sret
charshow:
mov bx,0b800h
mov es,bx ;ES指向显示缓冲区
mov al,160
mov ah,0
mul dh ;写入时的偏移,存放在AX
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0
charshows:
cmp bx,top
jne noempty
mov byte ptr es:[di],' '
;字符以\0结尾
jmp sret
noempty:
mov al,[si][bx]
mov es:[di],al ;显示字符
inc bx
add di,2 ;偏移2个字节写字符
jmp charshows ;显示字符串
sret:
pop es
pop di
pop dx
pop bx
ret
code ends
end start
3.2 实验结果
4. 总结
-
本文介绍了基于 int 16h 中断例程的 0 号功能从键盘缓冲区读取内容,如果缓冲区为空,则循环等待直到读取成功
-
参考:汇编语言/王爽著.——北京:清华大学出版社,2003