不同类型内中断的区分-中断类型码
8086cpu中在下面4种情况下会产生内中断:(1),除法错误 (如之前提到的除法溢出) (2),单步执行 (3),执行into指令 (4),执行int指令。那么当内中断发生时cpu如何来区分到底是哪种中断源呢?
通过中断类型码,这是一个字节数据,一共可以表示256种中断信息的来源。上述中断信息对应的中断类型码为:(1),除法错误:0 (2),单步执行:1 (3),执行into指令:4 (4),执行int指令,该指令的格式为int n,其中n为字节型立即数,是提供给cpu的中断类型码。(如前面经常用到的 int 21h)
如何找到相对应的中断处理程序-中断向量表
一旦发现了某种内中断的产生后,需要执行相关的中断处理程序来对中断进行处理。cpu要想执行中断处理程序的话,就需要让CS:IP指向它,那么从哪里找到相应的中断处理程序入口地址呢?
中断向量表,顾名思义,这个表里面存储着中断向量,而每一个中断向量就是一个中断处理程序的入口地址,在内存高地址处存放CS,低地址存放IP。有256种中断源,那么就有256种中断向量,二者是一一对应的。中断向量表存储在内存的0000;0000-0000:03ff之间的1024个内存单元处。
对于N号内中断,它的中断处理程序入口地址中的段地址为4*
N+2,偏移地址为4*
N
中断过程和中断处理程序
中断过程:
(1)从中断信息中取得中断类型码N
(2)标志寄存器的值入栈(中断过程会改变标志寄存器的值,故先将其保存)。pushf
(3)设置标志寄存器的第8位TF和第9位IF的值为0。TF=0,IF=0
(4)CS的内容入栈。push cs
(5)IP的内容入栈。push ip
(6)读取相应的中断处理程序的入口地址用来设置CS和IP。(IP)=4*
N,(CS)=4*
N+2
中断处理程序:
(1)保存用到的寄存器
(2)处理中断
(3)恢复用到的寄存器
(4)用iret指令返回,(pop IP,pop CS,popf 刚好对应于中断过程的寄存器入栈顺序,用来恢复cpu中断前的现场环境)
单步执行
cpu在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断。单步中断的中断类型码为1,它的中断过程为:(1)取得中断类型码1(2)标志寄存器入栈,TF、IF置为0(3)CS、IP入栈(4)设置(IP)=1*
4,(CS)=1*
4+2
Debug的单步执行t命令就是利用了cpu的单步中断功能。首先,Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令;然后,在使用t命令执行指令时,Debug将TF设置为1,使得cpu工作于单步中断方式下,因此在cpu执行完这条指令后引发单步中断,而执行单步中断的中断处理程序会将所有寄存器的内容显示在屏幕上,并等待输入命令。
如果在TF=1时引发单步中断转而执行中断处理程序。而此时TF=1,则在执行中断处理程序的第一条指令后又引发单步中断,又得去执行中断处理程序,但是又因为TF=1引发单步中断,…从而陷入死循环中。所以在执行中断处理程序前需要将TF设置为0,这也是我们之前所做的工作。
特殊情况(向ss寄存器中传送数据)
在ss寄存器中传送数据后,即使发生中断,cpu也不会响应。因为ss:sp联合指向栈顶,对它们的设置应该连续完成,否则在中断过程中的寄存器入栈保存操作会出现错误。所以:我们应该将设置ss和sp的指令连续存放,使得设置sp的指令紧接着设置ss的指令执行。
Debug利用了cpu的单步中断功能,在mov ss,ax指令执行后,cpu不响应任何中断,所以Debug也没法将此时的寄存器状态用中断处理程序来显示出来,只有当下一步设置sp的指令执行后,cpu可以进行中断响应了,Debug的t命令才能执行单步中断的中断处理程序来显示寄存器的内容。
实验12
编写0号中断的处理程序,使得在除法溢出发生时,在屏幕中间显示字符串“divede error!",然后返回到DOS。
assume cs:code
code segment
start: mov ax,cs
mov ds,ax
mov si,offset s0
mov ax,0
mov es,ax
mov di,200h
cld
mov cx,offset s0end-offset s0
rep movsb 安装中断处理程序到0000:0200处
mov ax,0
mov ds,ax
mov word ptr [0*4],200h
mov word ptr [0*4+2],0 更改中断向量表
mov ax,4x00h
int 21h
s0: jmp short st
db "divide error!"
st: mov ax,cs
mov ds,ax
mov si,202h
mov ax,0b800h
mov es,ax
mov di,12*160+32*2
mov cx,13
lo: mov al,[si]
mov es:[di],al
inc si
add di,2
loop lo
mov ax,4c00h
int 21h
s0end:nop 中断处理程序
code ends
end start