任何一个通用CPU,都可以在执行完当前正在执行的指令之后,检测到从CPU外部发送过来的或内部产生的一种特殊信息,并且可以立即对所接收的信息进行处理。这种特殊的信息,称为中断信息
中断在于:CPU不再接着(刚执行完的指令)向下执行,而是转去处理这个特殊信息
中断信息可以来自CPU的内部和外部
内中断的产生
当CPU内部产生下面的情况时,将产生相应的中断信息
除法错误,例:除法溢出
单步执行
执行
into指令执行
int指令
8086CPU用称为中断类型码的数据来标识中断信息的来源
中断类型码为一个字节型的数据,可表示256种中断信息的来源
以上4种中断源,在8086CPU中的中断类型码为:
除法错误:0
单步执行:1
执行
into指令:4执行
int指令:该指令格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码
中断处理程序
用来处理中断信息的程序被称为中断处理程序
CPU在收到中断信息后,如何根据中断信息确定其处理程序的入口
中断类型码的作用就是用来定位中断处理程序的。如何根据8位中断类型码得到中断处理程序的段地址和偏移地址呢?
中断向量表
CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址
中断向量,即中断处理程序的入口地址
中断向量表,即中断处理程序入口地址的列表
中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口

对于8086CPU,中断向量表指定存放在内存地址0处,0000:0000到0000:03FF的1024个单元中
中断向量表中,一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址
可见,CPU通过中断类型码,查找中断向量表,就可以得到中断程序的入口地址
中断过程
通过中断类型码到中断向量表中找到中断向量,并用它设置CS和IP,这个工作由CPU的硬件自动完成,称为中断过程
中断过程:
从中断信息中取得中断类型码
N标志寄存器的值入栈
pushf设置标志寄存器的第8位
TF和第9位IF的值为0TF=0,IF=0CS的内容入栈push CSIP的内容入栈push IP从内存地址为中断类型码*4和中断类型码*4+2的两个字单元中读取中断处理程序的入口地址设置
IP和CS(IP)=(N*4),(CS)=(N*4+2)
CPU收到中断信息,首先引发中断过程,硬件在完成中断过程后,CS:IP将指向中断处理程序的入口,CPU开始执行中断处理程序
中断处理程序和iret指令
中断处理程序
由于CPU随时都可能检测到中断信息,即CPU随时都可能执行中断处理程序,所以中断处理程序必须一直存储在内存某段空间之中。而中断处理程序的入口地址,即中断向量,必须存储在对应的中断向量表表项中
中断处理程序的编写方法:
保存用到的寄存器
处理中断
恢复用到的寄存器
用
iret指令返回
iret指令
iret指令描述为:
1 | pop IP |
iret通常和硬件自动处理的中断过程配合使用
中断过程中,寄存器入栈的顺序为标志寄存器、CS、IP,iret指令的出栈顺序为IP、CS、标志寄存器,实现了执行中断处理程序前中断过程进行保存现场的工作,iret指令执行后,恢复现场的工作
除法错误中断的处理
0号中断,除法错误中断的处理
当CPU执行div等除法指令的时候,若发生除法溢出错误,将产生中断类型码为0的中断信息,CPU将检测到这个信息,然后引发中断过程,转去执行0号中断所对应的中断处理程序
1 | mov ax,1000h |

0号中断处理程序的功能:显示提示信息Divide overflow后,返回到操作系统中
编程处理0号中断
重新编写0号中断处理程序,功能时在屏幕中间显示overflow!,然后返回到操作系统
分析:
CPU进行中断过程编写中断处理程序
do0相关处理
向显示缓存区送字符串
overflow!返回
DOS
do0在内存中的存放位置内存
0000:0000–0000:03FF,大小为1KB的空间存放中断向量表,8086CPU支持256个中断,但实际上,系统中要处理的中断事件未达到256个,所以在中断向量表中,许多单元是空的一般情况下,从
0000:0200–0000:02FF的256个字节空间所对应的中断向量表项为空可以将
do0传送到内存0000:0200处将
do0的入口地址,即0000:0200登记在中断向量表的对应表项中。0号中断的段地址存放在0*4+2字单元中,偏移地址存放在0*4字单元中
将
do0的段地址0存放在0000:0002字单元中,将偏移地址200h存放在0000:0000字单元中
程序框架如下
1 | assume cs:code |
程序执行时,首先执行do0安装程序,将do0的代码复制到内存0:200处;然后设置中断向量表,将do0的入口地址,即偏移地址200H和段地址0,保存在0号表项中。完成后,程序返回。do0的代码虽然在程序中,但不在程序执行时执行,它是在除法溢出发生的时候才得以执行的中断处理程序
安装程序
使用movsb指令,将do0的代码送入0:200处
1 | assume cs:code |
-是编译器识别的运算符号,编译器可以用它来进行两个常数的减法
汇编编译器可以处理表达式
例:指令mov ax,(5+3)*5/10,被编译器处理为指令mov ax,4
do0
do0程序主要任务是显示字符串
1 | assume cs:code |
设置中断向量
将do0的入口地址0:200,写入中断向量表的0号表项中,使do0成为0号中断的中断处理程序
0号表项的地址为0:0,0:0字单元存放偏移地址,0:2字单元存放段地址
1 | mov ax,0 |
单步中断
基本上,CPU在执行完一条指令之后,若检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程
中断类型码为1,单步中断
中断过程如下:
取得中断类型码1
标志寄存器入栈,
TF、IF设置为0CS、IP入栈(IP)=(1*4),(CS)=(1*4+2)
Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令。然后,在使用t命令执行指令时,Debug将TF设置为1,使CPU工作于单步中断方式下,则在CPU执行完这条指令后就引发单步中断,执行单步中断的中断处理程序,所有寄存器的内容被显示在屏幕上,并且等待输入命令
若在执行单步处理程序之前,TF=1,则CPU在执行完中断处理程序的第一条指令后,又要产生单步中断,则又要转去执行单步中断的中断处理程序,在执行完中断处理程序的第一条指令后,又要产生单步中断,则又要转去执行单步中断的中断处理程序。。。陷入无限循环
避免无限循环的方法是,在进入中断处理程序之前,设置TF=0,从而避免CPU在执行中断处理程序的时候发生单步中断
响应中断的特殊情况
一般情况下,CPU在执行完当前指令后,若检测到中断信息,就响应中断,引发中断过程
在某些情况下,CPU在执行完当前指令后,即便是发生中断,也不会响应
当执行完向ss寄存器传送数据的指令后,即便发生中断,CPU也不会响应。因ss:sp联合指向栈顶,若响应中断,ss改变,sp未改变,则ss:sp未指向正确的栈顶,将引发错误。所以应利用此特性,将设置ss和sp的指令连续存放
所以,当使用Debug进行单步执行时,设置好ss寄存器后,CPU未响应单步中断,继续执行设置sp寄存器的指令,之后响应下一次单步中断。单步执行显示结果中未体现设置sp指令的过程,但此指令已经被执行了