引言
大多数有用的程序都需要处理用户的输入,键盘输入是最基本的输入
程序和数据通常需要长期存储,磁盘是最常用的存储设备
BIOS为这两种外设的I/O提供了最基本的中断例程,
我们已经讲过,键盘输入将引发9号中断,BIOS提供了int 9中断例程。
cpu在9号中断发生后,执行 int 9中断例程,从60h端口中读出扫描码,并将其转化为相应的ASCII码或状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中。
一般的键盘输入,在cpu执行完int 9中断例程后,都放到了键盘缓冲区中。
键盘缓冲区中有16个字单元,可以存储15个按键的扫描码和对应的ASCII码
17.2 使用int 16h中断例程读取键盘缓冲区
BIOS提供了int 16h中断例程供程序员调用。
int 16h中断例程中包含的一个最重要的功能是从键盘缓冲区中读取一个键盘输入,该功能的编号为0
下面的指令从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除:
mov ah,0
int 16h
结果:
ah=扫描码
al=ASCII码
int 16h中断例程的0号功能,进行如下的工作:
1)检测键盘缓冲区中是否有数据
2)没有则继续做第1步。
3)读取缓冲区第一个字单元中的键盘输入。
4)将读取的扫描码送入ah,ASCII码送入al
5)将已读取的键盘输入从缓冲区删除。
可见,BIOS的int 9中断例程和int 16h中断例程是一对相互配合的程序,int 9中断例程向键盘缓冲区中写入,int 16h中断例程从缓冲区中读出。
他们写入和读出的时机不同,int 9中断例程在有键按下的时候向键盘缓冲区中写入数据
而int 16h中断例程是在应用程序对其进行调用的时候,将数据从键盘缓冲区中读出。
我们在编写一般的处理键盘输入的程序的时候,可以调用int 16h从键盘缓冲区中读取键盘的输入。
;编程: ;接收用户的键盘输入,输入“r”,将屏幕上的字符设置为红色:输入“g”, ;将屏幕上的字符设置为绿色;输入“b ”,将屏幕上的字符设置为蓝色。 ;A、B、C处的程序指令比较有技巧,请读者自行分析 assume cs:code code segment start: mov ah,0 int 16h mov ah,1 ;A cmp al,'r' je red cmp al,'g' je green cmp al,'b' je blue jmp short sret red: shl ah,1 ;B green: shl ah,1 ;C blue: 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
17.3 字符串的输入
用户通过键盘输入的通常不仅仅是单个字符而是字符串
下面我们讨论字符串输入中的问题和简单的解决方法。
最基本的字符串输入程序,需要具备下面的功能:
1)在输入的同时需要显示这个字符串
2)一般在输入回车符后,字符串输入结束。
3)能够删除已经输入的字符。
;最基本的字符串输入程序,需要具备下面的功能: ;(1) 在输入的同时需要显示这个字符串; ;(2)一般在输入回车符后,字符串输入结束; ;(3)能够删除已经输入的字符。 ;编写一个接收字符串的输入子程序,实现上面三个基本功能。 ;因为在输入的过程中需要显示,子程序的参数如下: ; (dh)、(dl)=字符串在屏幕上显示的行、列位置; ; ds:si 指向字符串的存储空间,字符串以O 为结尾符。 assume cs:code code segment start: call getstr return: mov ax,4c00h int 21h ;完整的接收字符串输入的子程序 getstr: push ax getstrs:mov ah,0 int 16h cmp al,20h jb nochar ;判断的是ASCII码小于0,说明不是字符 mov ah,0; call charstack;字符入栈 mov ah,2 call charstack;显示栈中的字符 jmp getstrs nochar: cmp ah,0eh;退格键的扫描码 je backspace cmp ah,1ch;回车键的扫描码 je enter jmp getstrs backspace:;退格 mov ah,1 call charstack;字符出栈 mov ah,2 call charstack;显示栈中的字符 jmp getstrs enter:;回车 mov al,0 mov ah,0 call charstack ;0入栈 mov ah,2 call charstack;显示栈中的字符 pop ax ret ;getstr ends ;功能子程序实现 charstack:jmp short charstart table dw charpush,charpop,charshow top dw 0 ;栈顶 charstart: push bx push dx push di push es cmp ah,2 ja sret 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] jmp sret charshow:mov bx,0b800h mov es,bx mov al,160 mov ah,0 mul dh 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],' ' jmp sret noempty:mov al,[si][bx] mov es:[di],al mov byte ptr es:[di+2],' ' inc bx add di,2 jmp charshows sret: pop es pop di pop dx pop bx ret code ends end start