本系列将讲解《汇编语言》一书,本节讲解**【汇编语言】17-键盘缓冲区逐步详解**。
本期源码,欢迎star:
https://github.com/ZYKWLJ/assembly4-homework
| 本节速览 |
|---|
| 1.键盘缓冲区是指? |
| 2.说一说按下A后,键盘缓冲区的输入? |
| 3.状态字shift、ctrl等是如何处理输入的? |
| 4.说一说最后变色程序的核心架构? |
1.键盘输入中断基础知识
我们已经讲过,键盘输入将引发9号中断 ,BIOS提供了int 9中断例程。CPU在9号中断发生后,执行int 9中断例程,从60h端口读出扫描码,并将其转化为相应的ASCII码或状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中。
一般的键盘输入,在CPU执行完int 9中断例程后,都放到了键盘缓冲区中。键盘缓冲区中有16个字单元,可以存储15个按键的扫描码和对应的ASCII码。
下面我们按照键盘缓冲区的逻辑结构,来看一下键盘输入的扫描码和对应的ASCII码是如何写入键盘缓冲区的。
实际上,键盘缓冲区是环形结构,在Linux内核里面有使用,这里为了方便,用线性表示。
2.按下键后,键盘缓冲区接受数据的分析
我们通过A,b,shift,shift_A的输入,实际梳理键盘缓冲区的变化。
1.初始状态
初始状态下,缓冲区里面什么都没有,为空。

2.按下A
按下 A 键,引发键盘中断;CPU 执行 int 9 中断例程,从 60h 端口读出 A 键的通码;然后检测状态字节,看看是否有 Shift、Ctrl 等切换键按下;发现没有切换键按下,则将 A 键的扫描码 1eh 和对应的 ASCII 码,即字母“a”的 ASCII 码 61h,写入键盘缓冲区。缓冲区的字单元中,高位字节存储扫描码,低位字节存储 ASCII 码。 此时缓冲区中的内容如下。

3.按下B
和按下A一样, 按下 B 键,将引发键盘中断;CPU 执行 int 9 中断例程,从 60h 端口读出 B 键的通码;然后检测状态字节,看看是否有切换键按下;发现没有切换键按下,将 B 键的扫描码 30h 和对应的 ASCII 码,即字母“b”的 ASCII 码 62h,写入键盘缓冲区。此时缓冲区中的内容如下。

4.按下shift
按下左 Shift 键,引发键盘中断;int 9 中断例程接收左 Shift 键的通码,设置0040:17处的状态字节的第1位为1,表示左 Shift 键按下。注意一定是尚未松起,从我们平时键盘输入就可以看出。
因为shift不写入键盘缓冲区,所以这里的缓冲区示意图不变。

5.按下A
按下 A 键,引发键盘中断;CPU 执行 int 9 中断例程,从 60h 端口读出 A 键的通码;检测状态字节,看看是否有切换键按下;发现左 Shift 键被按下,则将A 键的扫描码 1Eh 和 Shift_A 对应的 ASCII 码,即字母“A”的 ASCII 码 41h,写入键盘缓冲区。此时缓冲区中的内容如下。

3.使用int 16读取键盘缓冲区的数据
1.基本的int 16读取功能
BIOS 提供了 int 16h 中断例程供程序员调用。int 16h 中断例程中包含的一个最重要的功能是从键盘缓冲区中读取一个键盘输入,该功能的编号为 0。下面的指令从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除:

结果:(ah)=扫描码,(al)=ASCII码。
同时,int16h中断例程会检测键盘缓冲区,发现缓冲区为空,则循环等待,直到缓冲区中有数据。
对应以上几步的内容,我们最先读取最先写入的数据,队列的关系:
其实这和我们的认知也是一样的,因为我们先打出来的字,最先显示,后打出来的,后面显示!很简单的道理。
1、第一次int 16


||
V

此时,ah中的内容为1Eh,al中的内容为61h。
可以看到,我们的数据是从头部开始读取,也就是**先写入,先读取!**符合认知。
接下来的读取也一样,不再赘述。但是要唯一注意的是,当键盘缓冲区里面的数据为空时,int 16中断程序会一直循环读取,发现写入了数据,就立马再读取!
2、总结int 16和int 9
我们总结一下int 16 的0号功能:

可见,BIOS 的 int 9 中断例程和 int 16h 中断例程是一对相互配合的程序,
int 9 中断例程向键盘缓冲区中写入,
int 16h 中断例程从缓冲区中读出。
它们写入和读出的时机不同,
int 9 中断例程是在有键按下的时候向键盘缓冲区中写入数据;
而 int 16h 中断例程是在应用程序对其进行调用的时候,将数据从键盘缓冲区中读出。
4.编程
从键盘接收一个字符,当输入 “r” 时,将屏幕上的字符设置为红色;当输入 “g” 时,将屏幕上的字符设置为绿色;当输入 “b” 时,将屏幕上的字符设置为蓝色;当输入 “q” 时,退出程序。
源码:
assume cs:code
code segment
start:
start1:
mov ah,0
int 16h ;read the word entered in the key buffer
mov ah,1
cmp al,'r'
je red
cmp al,'g'
je green
cmp al,'b'
je blue
cmp al,'q'
je sret
jmp start1 ;Infinite loop unless q is entered.
red:
shl ah,1
green:
shl ah,1
blue:
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
s:
and byte
键盘缓冲区详解与编程应用

最低0.47元/天 解锁文章
2801

被折叠的 条评论
为什么被折叠?



