汇编语言 第十二章 内中断
中断信息,可以理解为更紧急、需要优先处理的信息,在执行指令过程中接收到中断信息,CPU会优先处理,而不是继续向下执行。
例如你正在刷抖音,厨房着火了你应该先去灭火而不是继续刷下一条抖音。
那么对于CPU而言,什么是需要优先处理的中断信息呢?有以下四种
- 除法错误。除数为0或者除法溢出
- 单步执行。debug中的T命令就是单步执行中断信息
- 执行into指令
- 执行int指令
那么CPU如何识别不同的中断信息?
使用的是中断类型码,(相当于用中断类型码给各类中断信息编号)中断类型码是一个字节型数据,可以表示256种中断信息的来源。(实际中断类型远少于256)
- 除法错误:0
- 单步执行:1
- 执行into指令:4
- 执行int指令:int n 其中n为字节型立即数,作为cpu的中断类型码
正在刷抖音(正常执行指令),你(CPU)根据冒出来的烟(中断类型码),发现这是着火了(对应某种中断信息),你知道要去救火了,那CPU接下来要干什么呢?
CPU当然是去执行相关的中断处理程序,CPU根据CS:IP执行指令,那么中断处理程序的入口地址在哪里呢?又要如何把它的赋给CS和IP呢?
CPU中的中断处理程序地址都存储在中断向量表。中断向量表在8086CPU中,CPU中存储在0000:0000~0000:03FF这1024个字节中(256个表项,和中断类型码一一对应)
每四个字节为一个表项,前两个字节存储中断处理程序的偏移地址,后两个字节存储其段地址。表项和中断类型码是一一对应的。例如除法指令类型码为0,它的中断处理程序的地址就存在第0个表项中,也就是0-3字节。中断类型码为N,对应中断处理程序偏移地址储存在4*N,段地址储存在4*N+2
中断过程:
- 从中断信息中取得中断类型码N
- 将标志寄存器的值入栈(因为中断过程中标志寄存器的值会被改变,将其入栈保存)pushf
- 将TF和IF均置0 ;TF = 0,IF = 0 CPU在执行完一条指令后,如果检测到TF = 1,那么就产生单步中断,执行相应的中断处理程序,而中断处理程序也是一条条指令组成的。执行中断处理程序之前TF = 1,执行完中断处理程序第一条之后,如果TF仍为1,这时就又要跳转,从头再执行中断处理程序,如此形成死循环。为避免这种执行中断处理程序的发生单步中断,CPU会再中断处理程序执行之前将TF置零。
- CS中的内容入栈 push CS
- IP中的内容入栈 push IP
- 从中断向量表中读取内存单元,(4*N)赋给IP,(4*N+2)赋给CS (IP) = (4*N) (CS) = (4*N+2)
到这时CS和IP都被设置好了,CPU开始执行中断处理程序。
中断处理程序:
类似于子程序,以下是常规的步骤:
- 保存用到的寄存器,入栈保存
- 处理中断
- 恢复用到的寄存器,出栈恢复
- 用IRET指令返回
iret指令:
出栈顺序与中断过程中的入栈相反,保证了初始值都不变。
pop IP
pop CS
popf
小小tips:
- 编译器可以识别并直接运算加减乘除(+、-、*、/)
- 如何知道一段代码的字节长度?可以用标号偏移地址相减表示。例如要知道循环s的长度,可以在loop s之后在写一行 send:nop offset send - offset s就是s段的长度了,不同的标号之间也可以这样处理。
响应中断的特殊情况:
执行完设置ss寄存器的指令后,不响应中断。中断信息的优先级比一般指令要高,相对一般指令优先执行;但设置ss的值优先级要比中断信息更高,执行完设置ss的指令及其下一条指令之后,才可能响应中断信息。所以应将设置ss和sp的指令连续存放。