【汇编语言】17-键盘缓冲区逐步详解

键盘缓冲区详解与编程应用

公粽号「专注Linux」,专注Linux内核开发

本系列将讲解《汇编语言》一书,本节讲解**【汇编语言】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 码。 此时缓冲区中的内容如下。

按下A后,键盘缓冲区的逻辑视图

3.按下B

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

按下B后,键盘缓冲区的逻辑视图

4.按下shift

按下左 Shift 键,引发键盘中断;int 9 中断例程接收左 Shift 键的通码,设置0040:17处的状态字节的第1位为1,表示左 Shift 键按下注意一定是尚未松起,从我们平时键盘输入就可以看出

因为shift不写入键盘缓冲区,所以这里的缓冲区示意图不变。

按下shift后,键盘缓冲区的逻辑视图

5.按下A

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

因为按着shift的,所以再按下A时,会检测到我们输入的是A,所以对应的ascii为41,但是键的位置依然是1E,这不变的!


3.使用int 16读取键盘缓冲区的数据

1.基本的int 16读取功能

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

int 16中断读取缓冲区内容的执指令

结果:(ah)=扫描码,(al)=ASCII码。

同时,int16h中断例程会检测键盘缓冲区,发现缓冲区为空,则循环等待直到缓冲区中有数据。


对应以上几步的内容,我们最先读取最先写入的数据,队列的关系:

其实这和我们的认知也是一样的,因为我们先打出来的字,最先显示,后打出来的,后面显示!很简单的道理。

1、第一次int 16

执行指令

指令执行前的键盘缓冲区

||

V

指令执行后的键盘缓冲区

此时,ah中的内容为1Ehal中的内容为61h

可以看到,我们的数据是从头部开始读取,也就是**先写入,先读取!**符合认知。

接下来的读取也一样,不再赘述。但是要唯一注意的是,当键盘缓冲区里面的数据为空时,int 16中断程序会一直循环读取,发现写入了数据,就立马再读取!


2、总结int 16和int 9

我们总结一下int 16 的0号功能:

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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值