任何一个通用的CPU,都可以在执行完当前正在执行的指令之后,检测到从CPU外部发送过来或内部产生的一种特殊信息,并可以立刻对接收到的信息进行处理,这种特殊的指令,我们将其称为 中断信息,中断信息可以来自CPU内部和外部,本章主要讨论来自CPU内部的中断信息
中断信息要求CPU马上进行某种处理,并向所要进行的该种处理提供了必备参数的通知信息
中断的意思指,CPU不再接着刚执行完的指令向下执行,而是转去处理这个特殊信息
12.1 内中断的产生
CPU内部有如下情况发生时,将会产生相应的中断信息:
1,除法错误,如执行div指令时产生的除法溢出
2,单步执行
3,执行into指令
4,执行int指令
CPU需要直到所接收到的中断信息的来源,所以中断信息中必须包含识别来源的源码,8086CPU用称为中断类型码的数据来标识中断信息的来源,中断类型码为一个字节数据,可以表示256种中断信息的来源
将中断信息的来源,简称为中断源,上述的4种中断源,在8086CPU种中断类型码如下:
1,除法错误:0
2,单步执行:1
3,执行into指令:4
4,执行int指令:该指令的格式为int n,指令种的n为字节型立即数,是提供给CPU的中断类型码
12.2 中断处理程序
CPU收到中断信息后,需要对中断信息进行处理,对中断信息如何处理,可以由我们编程,用来处理中断信息的程序称为 中断处理程序,需要对不同的中断信息编写不同的处理程序
CPU在收到中断信息后,应该转去执行该中断信息的处理程序,8086CPU若要执行某处的程序,就需要将CS:IP指向它的入口,CPU的设计者必须在中断信息和其处理程序的入口地址之间建立某种联系,使得CPU可以根据中断信息找到要执行的处理程序
中断信息种包含有标识中断源的类型码,中断类型码的作用就是用来定位中断处理程序,如CPU根据中断类型码4,就明白需要找到4号中断的处理程序
但要定位中断处理程序,需要知道它的段地址和偏移地址
12.3 中断向量表
CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址,中断向量表就是中断处理程序入口地址的列表
中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口,CPU只要知道了中断类型码,就可以将中断类型码作为中断向量表的表项号,定位相应的表项,从而得到中断处理程序的入口地址
中断向量表在内存中存放,对于8086PC机,中断向量表指定放在内存地址0处,从内存0000:0000~0000:03EF的1024个单元中存放着中断向量表,一个表项存放一个中断向量,即一个中断处理程序的入口地址,这个入口地址包括 段地址和偏移地址,所以一个表项占2个字,高地址字存放段地址,低地址字存放偏移地址
12.4 中断过程
可以使用中断类型码,在中断向量表中找到中断处理程序的入口,这个入口地址的最终目的是设置CS和IP,使CPU执行中断处理程序,这个工作是由CPU的硬件自动完成的。CPU硬件完成这个工作的过程被称为中断过程
CPU在执行完中断处理程序后,应该返回原来的执行点继续执行下面的指令,所以在中断过程中,在设置CS:IP之前,还要将CS和IP的值保存起来
8086CPU在收到中断信息后,所引发的中断过程:
1,从中断信息中取得中断类型码
2,标志寄存器的值入栈(因为中断过程中要改变标志寄存器的值,所以要将其保存在栈中)
3,设置标志寄存器的第8位TF和第9位IF的值为0
4,CS的内容入栈
5,IP的内容入栈
6,从内存地址为 中断类型码乘4 和 中断类型码乘4 + 2的两个字单元中读取中断处理程序的入口地址设置IP和CS
在最后一步完成后,CPU开始执行由程序员编写的中断处理程序
12.5 中断处理程序和 iret 指令
由于CPU随时都可能检测到中断信息,也就是说,CPU随时都可能执行中断处理程序,所以中断处理程序必须一直存储在内存的某段空间内,而中断处理程序的入口地址,即中断向量,必须存储在对应的中断向量表中
中断处理程序的编写方法步骤:
1,保存用到的寄存器
2,处理中断
3,恢复用到的寄存器
4,用 iret 指令返回
iret指令的功能用汇编描述为:
pop IP
pop CS
popf
iret通常和硬件自动完成的中断过程配合使用,在中断过程中,寄存器入栈的顺序是标志寄存器,CS,IP,而iret的出栈顺序是IP,CS,标志寄存器,刚好和其相对应,实现了用执行中断处理程序前的CPU现场恢复标志寄存器CS,IP的工作,iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序
12.6 除法错误中断的处理
当CPU执行div等除法指令时,如果发生了除法溢出的错误,将产生中断类型码为0的中断信息,CPU将检测到这个信息,然后引发中断过程,转去执行0号中断所对应的中断处理程序
mov ax,1000h
mov bh,1
div bh
当使用debug调试上面的程序时,执行到 div bh时,发生了除法溢出错误,从而引发中断过程,CPU执行0号中断处理程序,系统中0号中断处理程序的功能:提示你的程序出现了一个除法溢出错误
12.7 编程处理0号中断
当理解中断过程后,尝试重新编写一个0号中断处理程序,它的功能是在屏幕中间显示 overflow ,然后返回到操作系统
分析:
1,当发生除法溢出时,产生0号中断信息,从而引发中断过程,CPU将执行以下工作:
(1),取得中断类型码 0
(2),标志寄存器入栈,TF,IF设置为0
(3),CS,IP入栈
(4),(IP)=(0乘4),(CS)=(0乘4 + 2)
2,当中断0发生时,CPU转去执行中断处理程序,将这段程序称为do0:
(1),相关处理
(2),向显示缓冲区送入字符串 overflow
(3),返回DOS
3,do0因该放在内存中,因为除法溢出随时都可能发生,CPU随时都可能将CS:IP指向do0的入口,执行程序
找到一块别的程序不会用到的内存区,将do0传送到里面即可,中断向量表是PC系统中最重要的内存区,只用来存放中断处理程序的入口地址,DOS系统和其它应用程序都不会随便使用这段空间,从0000:0200至0000:02EF的256个字节的空间所对应的中断向量表都是空的
所以将do0的段地址0存放在0000:0002字单元中,将偏移地址200H存放在0000:0000字单元中
通过分析,需要做到:
1,编写可以显示overflow的中断处理程序 do0
2,将do0送入内存0000:0200处
3,将do0的入口地址0000:0200存储在中断向量表0号表项中
12.8 安装
可以使用movsb指令,将do0的代码送入0:200处
12.9 do0
对于字符串 overflow,也要将其放入一段不会被覆盖的空间中,如果只是申请空间存放overflow,程序一次执行完后,它所占用的内存空间会被释放,其中存放的overflow也可能被别的信息所覆盖
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset do0
mov ax,0
mov es,ax
mov di,200h
mov cx,offset do0end - offest do0
cld
rep movsb
设置中断向量表
mov ax,4c00h
int 21h
do0:jmp short do0start
db "overflow"
do0start: mov ax,cs
mov ds,ax
mov si,202h ;设置ds:si指向字符串
mov ax,0b800h
mov es,ax
mov di,12*160+36*2 ;设置es:di指向显存空间的中间位置
mov cx,9 ;设置cx为字符串长度
s: mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
12.10 设置中断向量
将do0的入口地址0:200,写入中断向量表的0号表项中,使do0成为0号中断的中断处理程序
0号表项的地址为0:0,其中0:0字单元存放偏移地址,0:2字单元存放段地址
mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0
12.11 单步中断
CPU在执行完一条指令之后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程
单步中断的中断类型码为1,它的中断过程如下:
1,取得中断类型码1
2,标志寄存器入栈,TF,IF设置为0
3,CS,IP入栈
4,(IP) = (1乘4) (CS) = (1乘4 + 2)
CPU只要一加电,就会从预设的地址开始一直执行下去,如果CPU不提供其它功能,就不可能有任何程序控制它在执行完一条指令后,去做别的事,但在使用debug时,debug可以控制CPU执行被加载程序中的一条指令,然后让它停下来,显示寄存器的状态
debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令,然后,使用t命令执行指令时,debug将TF设置为1,使得CPU工作于单步中断方式下,则在CPU执行完这条指令后就引发单步中断,执行单步中断的中断处理程序,所有寄存器中的内容被显示在屏幕上,并等待输入命令
CPU提供单步中断功能的原因是,为单步跟踪程序的执行过程,提供了实现机制
12.12 响应中断的特殊情况
一般情况下,CPU在执行完当前指令后,如果检测到中断信息,就响应中断,引发中断过程,可有些情况下,CPU在执行完当前指令后,即便发生中断,也不会响应
如:
在执行完向ss寄存器传送数据的指令后,即便是发生中断,CPU也不会响应,这样的主要原因是,ss:sp联合指向栈顶,而对它们的设置应该连续完成,如果在执行完设置ss的指令后,CPU响应中断,引发中断过程,要在栈中压入标志寄存器,CS和IP的值。ss改变,但sp未改变,ss:sp指向的不是正确的栈顶,将引起错误,所以CPU在执行完设置ss的指令后,不响应中断