汇编语言 第12章 内中断
内部中断的产生
当8086 CPU内部发生下面情况时,将产生相应中断信息。
- 除法错误,比如,执行div产生除法溢出
- 单步执行
- 执行into指令
- 执行int指令
以上不同的中断信息,CPU要作不同的处理, 因此,CPU首先要知道中断信息来源,那么中断信息就必须包含识别来源的编码。 8086 CPU用称为中断类型码的数据来标识中断信息的来源。
中断信息码为一个byte,可表示256种中断信息。 上述中断的相关中断码为:
- 除法错误:0
- 单步执行:1
- into指令:4
- int n 指令(n为byte型立即数):n
int即 interrupt,中断。 into应该是 interrupt out的简称, 之所以只需要一个数字4,猜测应该是统一跳转到外部程序,由外部程序处理, 这样只需外部程序考虑不同处理方式。
中断处理程序
CPU收到中断信息后,需要处理中断,我们可以自己编写相关中断程序。
首要问题是,收到中断信息后,如何根据中断信息,确定处理程序的入口。 因此,CPU设计者需要在中断信息和对应处理中断程序之间建立某种联系。
中断类型码的作用就是定位中断处理程序。 那么就要在字码和中断处理地址之间建立关系, 一个数组就可以搞定,没错,8086中就是存放256个中断处理程序地址的中断向量表。
中断向量表
对于8086 CPU,中断向量表存放在0000:0000到0000:03FF这1024个单元中, 对于256个中断地址,正好一个中断地址对应4个byte,CS和IP各占2byte。
中断过程
中断过程由CPU硬件实现,CPU收到中断信息后,首先引发中断过程。 硬件完成中断过程后,CS:IP将指向中断处理程序入口,CPU开始执行中断程序。
有一个问题需要考虑,CPU执行完中断后,应该返回原来执行的位置。 所以,中断过程中,在设置CS:IP之前,需要先将原CS:IP保存起来。
因此,完整的中断过程如下:
- 取得中断类型码
- 标志寄存器的值入栈(因中断会改变标志寄存器原来的值)
- 设置标志寄存器的TF和IF的值为0
- CS内容入栈
- IP内容入栈
- 将内存中[中断码4]和[中断码4+2]两个字单元的数据设置到IP和CS中。
- 执行中断程序
中断处理程序和iret指令
iret(interrupt return)用于中断程序的返回,相当于: pop IP pop CS popf
单步中断
如上所述,中断是会设置标志位TF和IF = 0, 而如果检测到标志位TF = 1(Test Flag),则产生单步中断。 CPU提供单步中断功能就是为单步跟踪程序的执行过程提供实现机制。
具体而言,
首先单补执行的中断码为1,所以要设置单步中断指令,
就要将其中断码设置为1,
设置之后,为了让程序单步执行(即每执行完一步后,立即执行中断码为1的程序)
但不可能每个代码都插入一个int 1
吧,所以用一个标志寄存器TF = 1
(Test Flag)来解决这个问题。
总的而言,设置单步中断分两步:
- 设置中断码为1的中断指令(例如可以显示寄存器值、或者某个参数值之类的)
- 单步执行处设置TF = 1,退出单步执行时设置TF = 0
响应中断的特殊情况
有些情况下,检测到中断后不能马上中断,例如:
mov ax, 1000h
mov ss, ax
mov sp, 0
在执行mov ss, ax
过程中,如果发生中断,sp这时还没有设置正确的值,
那么如果发生中断,则栈指针将指向错误的内存地址。
而且执行mov ss, ax
后,应该马上执行mov sp, 0
操作,而不能插入其他操作。