int 指令:
int 指令的格式为 int n ,n 为中断类型码,用 int 指令,可以随时调用任何一个处理中断程序。执行 int n 相当于引发一个中断类型码为 n 的中断过程。它的步骤和中断过程的步骤是一样的:
- 从中断信息中取得中断类型码 n
- 标志寄存器入栈,设置 TF ,IF 为0(防止无限进执行单步中断)
- 将CS,IP 入栈
- 将CS:IP设置为指向处理中断程序的入口
使用 int 引发中断时,即使并没有中断源,也会去执行处理中断程序。
系统有时候会将一些有一定功能的程序以中断处理程序的方式提供给其他程序调用,我们可以用 int 指令来对其进行调用。
编写供应用程序调用的中断程序
假如我们要编写一个将一串以0结尾的字符串转化为全是大写字母的字符串。
首先我们在那个要调用这个程序的程序中要先设置一些东西,比如我们的字符串,以及我们要获取字符串的地址。
然后我们要编写一个安装程序,以及我们的中断程序,安装程序将我们的中断程序安装到指定内存,并且设置向量表 7ch 指向我们的程序入口。
这一段是我们的安装程序,我们的中断处理程序是跟在这段程序后面的,是它的一部分。
这是一个完整的安装程序,里面包括了我们自己写的中断处理程序。
对于中断我们要注意的是:中断过程和中断程序是两个东西,中断过程是在CPU接受到中断源发出的中断信息后,由硬件自己进行的一个过程,它的作用就是从中断信息中提取中断类型码,然后将标志寄存器压入栈,再将CS,IP压入栈,再根据中断类型码在向量表中找到对应的程序入口,设置CS:IP指向程序入口。然后后面CPU再执行指令时,自然会去执行CS:IP指向的地方,就是去执行中断处理程序。所以中断处理程序后面都要有一个iret指令。
对 int ,iret,和栈的深入理解:
如果我们要编写一个中断程序,用来实现 loop 的功能。首先我们要知道,loop 它是通过使IP加上 LOOP指令的后面一条指令减去要转移到的标号的指令的位移来实现循环的。那么我们可以模仿这种机制来编写一个程序。
首先我们需要获得从标号开始到我们调用程序的 int 指令结束的程序长度,这个就是我们要的位移。然后我们在程序中需要改变IP的值,CS的值不用改变,因为都在一个段中。要注意的是,我们在调用中断程序前有个中断过程,其中有一个把IP压入栈的动作,并且中断程序执行到最后有个 iret 指令,它把IP从栈中弹出来。所以,我们只需要在栈中改变IP的值,就可以了。但是又有一点需要注意,就是我们在栈中改变栈里面存放的内容,那肯定要用到SP,但是SP就是用来指向栈的,用起来会很麻烦,所以后面要恢复它会有点麻烦,这里我们可以用到 基数指针寄存器BP,它也可以像SP一样来指向栈,并且用 [bp] 时,它的默认段地址在SS中。所以我们可以先将BP的值压入栈,然后将SP的值给它,然后再来对栈中IP的值进行改写。
BX中存放的就是位移,因为之前有一个把BP压入栈的操作,所以SP又减了2,所以后面要将BP先加2,最后弹出BP,然后再使用 iret 指令。
BIOS和DOS所提供的中断例程
在系统的ROM中存放了一套程序,称为BIOS ,也就是基本输入输出系统,它主要包扩了以下几个方面:
- 硬件系统的检测和初始化程序
- 外部中断和内部中断的中断例程
- 用于对硬件设备进行输入输出操作的中断例程
- 其他和硬件系统相关的中断例程
DOS也提供了中断例程,不过和硬件相关的DOS中断例程中,一般都调用了BIOS的中断例程。
BIOS和DOS中断例程的安装过程
- 第一步,开机,开机后,CPU加电,然后初始化CS=0FFFF,IP=0,然后自动从CS:IP处开始执行指令。然后FFFF:0处有一条跳转指令,CPU又会跳转去执行BIOS中的硬件检测和初始化程序。
- 第一步中的初始化程序将建立BIOS所支持的中断向量,就是把BIOS所提供的中断例程的入口地址登记在中断向量表中,因为BIOS的中断例程是在ROM中的,所以我们不用编写,它是一直存在的。
- 硬件系统的检测和初始化完成后,就调用 int 19h 进行操作系统的引导,从此,将计算机交由操作系统控制。
- DOS启动后,除完成其他工作外,还会将它提供的中断例程安装到内存,并且建立对应的中断向量。
BIOS中断例程应用
一般来说,一个中断例程往往包含多个子程序,而在中断例程内部,我们通过传递参数来决定调用哪个子程序。BIOS和DOS中都用 ah 来传递内部子程序的编号。我们举个例子来看看BIOS的例程:
首先我们向AH传递了参数2,这个表示执行例程中的置光标子程序,它将会把光标放在我们指定的位置。然后下面我们再传递一些参数,一些属性对应的寄存器如下:
bh: 页号 bl: 颜色属性
dh: 行号 dl: 列号
ah: 子程序编号 al: 要显示的字符
CX : 字符重复个数
向ah 传递 9 ,就是在光标位置显示字符,向BL传递的颜色属性和向显示缓冲区传递的是一样的。
可以直接传递二进制数。
DOS中断例程应用
我们之前一直使用的 mov ax,4c00h
int 21h
其实是 mov ah,4c
mov al,0
int 21h
向 ah 传递 4c 其实就是调用 21h号例程中的 4c 号子程序,功能为程序返回。给 al 传递的为返回值。
同样,我们向AH传递9,是在光标位置显示字符。而在DOS的例程中屏幕会显示DS:DX所指向的地址中的内容,我们的字符串应以$结尾,当读到这个字符时,会结束显示,这个字符不会显示。