马上过年了,这几天要么在帮忙,要么在玩。今天是年三十,上午没什么事,我要好好学一下。
外中断
外中断信息
有一种中断信息,来自于CPU的外部,当CPU外部有需要处理的事情发生的时候。比如说,外设的输入到达,芯片会向CPU发出相应的中断信息。CPU在执行完当前的指令后,可以检测发送过来的中断信息,引发中断过程,处理外设的输入
在PC中,外中断源一共有以下两类:
可屏蔽中断
可屏蔽中断是CPU可以不响应的外中断。CPU是否可以响应可屏蔽中断,要看标志位寄存器IF的位的设置。当CPU检测到可屏蔽中断信息是,如果IF = 1,则CPU在执行完当前指令后响应中断,引发中断;如果IF= 0,则不响应可屏蔽
可屏蔽中断程序的所引发的中断过程,基本和内中断的中断过程相同。因为可屏蔽中断信息来自于CPU外部,中断类型码通过数据总线送入CPU;而内中断的中断类型码在CPU内产生的
现在,我们可以解释中断过程中将IF置为0的原因了。将IF置为0的原因就是,在进入中断和程序之后,禁止其他的可屏蔽中断。如果在中断过程中需要处理可屏蔽中断,可以用指令将IF置1。。8086CPU提供的设置IF的指令如下:
sti,设置IF = 1
cli,设置IF = 0
不可屏蔽中断
不可屏蔽中断时CPU必须响应的外中断。当CPU检测到不可屏蔽中断信息时,则在执行完当前命令后,立即响应,并引发中断过程
对于8086CPU,不可屏蔽中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码,而是直接触发。不可屏蔽中断的中断过程为:
- 标志寄存器入栈,IF=0,TF=0
- CS,IP入栈
- (IP) = (8),(CS)= (0AH)
几乎所有的外设引发的外中断,都是可屏蔽中断。当外设有需要处理的事件时(比如说键盘输入)发生时,相关芯片向CPU打出可屏蔽中断信息。不可屏蔽中断时在系统中有必须处理的紧急情况发生时用来通知CPU的中断信息
PC机的键盘处理过程
通过键盘的响应过程。我们可以感受一下外设输入的过程
键盘输入
键盘上的键相当于开关,键盘中有一个芯片。当按下一个键时,芯片就会产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60h。松开按下的键时,也产生一个扫描码,扫描码说明了松开的键在键盘上的位置。松开时,产生的扫描码也送到端口60h中
- 通码:按下一个键产生,第7位为0
- 断码:松开一个键产生,第7位为1
一个扫描码的长度为一个字节,所以有 断码 = 通码 + 80H
引发9号中断
当键盘的输入到达60H端口时,相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息。CPU检测到该中断信息后,如果IF=1,则响应中断,引发中断过程,转去执行int 9
中断例程
执行 int 9
中断例程
BIOS提供了int 9中断例程,用来进行基本的键盘输入处理,其工作如下:
- 读出60h端口中的扫描码
- 如果是字符键的扫描码,将该扫描码和它所对应的(ASCII码)送入内存中的BIOS键盘缓冲区;如果是控制键(Ctrl)和切换键(CapsLock)的扫描码,则将其转变为状态字节(用二进制位记录控制键和切换状态的字节)写入内存中存储状态字节的单元
- BIOS键盘缓冲区在系统启动后,用来存放
int 9
中断例程中所接收的键盘输入。该内存区可以存储15个键盘输入,因为int 9
中断例程除了接受扫描码外,还要产生对应的字符码。所以在BIOS键盘缓冲区,一个键盘输入用一个字单元存放(高位存放扫描码,低位存放字符码)
关于状态码如下:

INT 9例程
编写int 9
例程
我们可以编写新的键盘中断例程,进行一些特殊工作。不过设计到部分的硬件操作细节,不过我们可以通过使用已经编写好的int 9例程覆盖这些操作
比如现在我们需要:在屏幕中间依次显示“a”~“z”,并可以让人看清。在显示的过程中,按下Esc键后改变颜色
我们可以先写出循环打印的程序
1 | assume cs:code |
接着我们使用int 9中断例程去实现变色
键盘输入到达60h端口后,会引发int 9 中断例程。我们可以编写int 9例程,功能如下:
- 从60H端口中读出键盘的输入
- 调用BIOS的int 9中断例程,处理其他硬件细节
- 判断是否位Esc的扫描码,如果是,改变颜色后返回;如果不是则直接返回
不过如何调用原int 9也是一个问题,在这里我们可以将其入口地址作为我们的函数入口,然后用以下方法模拟调用:
- 标志寄存器入栈
- IF=0,TF=0
- call dword ptr ds:[0]
对于(1),可以使用 pushf
实现
对于(2),可以用下面的指令实现
1 | pushf |
则综上的int模拟过程为:
1 | pushf |
知道原理之后我们可以实现:
1 | assume cs:code |
安装int 9例程
刚刚是简介使用了原int 9中断例程的功能,现在我安装一个新的int 9中断例程,使得原int9中断例程的功能得到拓展
功能:在DOS下,按F1键后改变当前屏幕的显示颜色,其他键照常处理
在开始之前需要解决几个问题,首先
- 改变屏幕的显示颜色
改变从B800H开始的4000个字节中的所有奇地址元素中的内容,当前屏幕的显示颜色即发生改变
1 | mov ax,08b00H |
- 其他的都是使用原int9例程处理即可,这里我们还需要调用原int9中断例程,所以需要保存原int9例程的入口地址:
由于安装程序在程序返回之后地址将丢失,所以我们将其保存在0:200后,而我们重写的int9例程,我们也将保存在0:204之后
现在准备就绪,开始编写
1 | assume cs:code |
实验十五

很简单,只要在上一个代码的基础上做修改即可
1 | assume cs:code |