中断信息可以来自CPU的内部和外部,当CPU的内部有需要处理的事情发生的时候,将产生需要马上处理的中断信息,引发中断过程。在第12章中,我们讲解了中断过程和两种内中断的处理。
这一章中,我们讲解另一种重要的内中断,由int指令引发的中断。
int指令的格式为:
int n,
n为中断类型码,它的功能是引发中断过程。
CPU执行int n指令,相当于引发一个n号中断的中断过程,执行过程如下
(1)取中断类型码n;
(2)标志寄存器入栈,IF=0, TF=0
(3) CS, IP入栈:
(4) (IP)=(n*4), (CS)=(n*4+2)
从此处转去执行n号中断的中断处理程序。
可以在程序中使用int指令调用任何一个中断的中断处理程序。例如,下面的程序:
assume cs:code code segment start:mov mov ax,0b800h mov es,ax mov byte ptr es:[12*160+40*2],'!' int 0 code ends end start
这个程序在Windows 2000中的DOS方一式下执行时,将在屏幕中间显示一个然后显示“Divide overflow”后返回到系统中。“!”是我们编程显示的,而overflow”是哪里来的呢?我们的程序中又没有做除法,不可能产生除法溢出。
“Divide 程序是没有做除法,但是在结尾使用了int 0指令。CPU执行int 0指令时,将引发中断过程,执行0号中断处理程序,而系统设置的0号中断处理程序的功能是显示“Divideoverflow",然后返回到系统。
可见,int指令的最终功能和call指令相似,都是调用一段程序。
一般情况下,系统将一些具有一定功能的子程序,以中断处理程序的方式提供给应用程序调用。我们在编程的时候,可以用int指令调用这些子程序。当然,也可以自己编写一些中断处理程序供别人使用。以后,我们可以将中断处理程序简称为中断例程。
INT指令(软件中断指令)共有四中不同的格式:
《1》 int n
n是中断号,这就允许用户程序调用256个中断服务子程序。
该指令2字节长度,第一字节是int机器码,第二字节是8位立即数,表示中断号。
CPU在执行到INT指令时,通过中断描述符表找到中断号对应的中断服务子程序的地址,(本质上就是一个异常处理程序的软件调用)
《2》 int 3
INT 3 是中断指令的一种特殊形式,仅有一个字节长。
调试器将该指令当作软件中断指令来用。调试的时候,当程序中的某一位置加断点的时候,调试器会把断点处指令编码的第一个字节替换为INT 3指令的编码。
当程序执行到INT 3,回向调试器申请系统调用,调试器因此获得CPU控制权。之后,再用原先的编码替换INT 3 编码。
《3》INTO 中断号4
如果溢出标志位为1,则INTO指令会产生一个软件中断,利用这个指令可以快速测试算术运算指令之后是否有溢出产生。
《4》BOUND 中断号5
BOUND reg,mem
其执行算法为:if(reg<[mem])or(reg>[mem+sizeof(reg)]) then INT 5
判断数组下表是否在合理范围内,不合理触发INT 5 中断,返回地址仍是BOUND
不管是哪种,都会发生
(1)标志寄存器入栈
(2)CS:EIP 寄存器入栈,
(3)通过中断号在中断描述符表中找到对应的描述符,并将对应的数据放入CS:EIP中、
CS入栈和出栈都是一个32位值,只有低16位有效。扩充的高16位无定义,目的是使堆栈保持与4字节边界对齐。这对80386的性能来说很重要