内存管理的中断功能
在C/C 语言环境中,若事先不知道数据的容量,那么,可通过动态申请空间的方法来解决数据的存储问题,这种动态数据结构可用中断21H所提供的存储管理功能来实现。
中断21H在内存管理方面所提供的主要功能如下:
48H——分配内存块
49H——释放内存块
4AH——重定义内存块的大小
58H——读取/设置内存分配策略,其最基本的分配策略有三种:第一满足、最好满足和最后满足
有关中断功能的详细描述和调用参数在此从略,需要查阅者可参阅附录3之内存分配功能。
有关存储分配策略的含义可参阅《操作系统》课程中“内存管理”部分的介绍。
8.3.8 读取和设置中断向量
中断向量是系统用来存放中断服务程序或系统参数的入口地址。在通常情况下,程序员不需要对中断向量表作任何操作,但在开发程序时,若要为某种特殊需要而提供新的中断处理程序时,则其就必须要操作中断向量表。
1、读取中断向量
(1)、DOS功能调用的方法
DOS提供了用系统调用的方法来读取中断向量,其中断21H之功能35H就能读取指定中断号的入口地址。其使用参数如下:
入口参数:AH=35H,AL=中断号
出口参数:ES:BX=中断处理程序的入口地址
例8.15 用功能调用的方法把中断n的入口地址保存到双字变量OldAddr中。
解: |
|||
|
…… OldAddr DD ? …… |
||
MOV |
AL, n |
;这里的n要用具体的中断号来定 |
|
MOV |
AH, 35H |
||
INT |
21H |
||
MOV |
word ptr OldAddr, BX |
||
MOV |
word ptr OldAddr 2, ES |
;把其入口地址保存在存储单元中 |
|
…… |
(2)、直接访问存储单元的方法
由前面的图8.2不难看出:中断向量表是存储在内存的第0段。若中断号为n,那么,其入口地址在表内的偏移量为4n。
例8.16 用直接访问存储单元的方法把中断n的入口地址保存到双字变量OldAddr中。
解: |
|||
|
…… OldAddr DD ? …… |
||
MOV |
AX, 0H |
||
MOV |
ES, AX |
;中断向量表存储在第0段内 |
|
MOV |
BX, 4*n |
||
MOV |
AX, ES:[BX] |
;读取中断入口地址的偏移量 |
|
MOV |
word ptr OldAddr, AX |
;保存中断入口地址的偏移量 |
|
MOV |
AX, ES:[BX 2] |
;读取中断入口地址的段地址 |
|
MOV |
word ptr OldAddr 2, ES |
;保存中断入口地址的段地址 |
|
…… |
2、设置中断向量
(1)、DOS功能调用的方法
中断21H之功能25H可为指定的中断号设置新的入口地址。其使用方法如下:
入口参数:AH=中断号,DS:DX=中断处理程序的入口地址
出口参数:无
例8.17 用功能调用的方法把子程序NewFunc设置为中断n的中断处理程序。
解: |
||||
|
…… |
|||
NewFunc |
PROC |
|||
…… |
||||
IRET |
;注意其返回指令 |
|||
NewFunc |
ENDP |
|||
…… |
||||
MOV |
AX, SEG NewFunc |
|||
MOV |
DS, AX |
;设置段地址寄存器 |
||
MOV |
DX, OFFSET NewFunc |
;设置偏移量 |
||
MOV |
AL, n |
;这里的n要用具体的中断号来定 |
||
MOV |
AH, 25H |
|||
INT |
21H |
|||
…… |
(2)、直接访问存储单元的方法
例8.18 用直接访问存储单元的方法把子程序NewFunc设置为中断n的中断处理程序。
解: |
||||
|
…… |
|||
NewFunc |
PROC |
|||
NewFunc |
…… |
|||
IRET |
;注意其返回指令 |
|||
ENDP |
||||
|
…… |
|||
MOV |
AX, 0H |
|||
MOV |
DS, AX |
|||
MOV |
BX, 4*n |
|||
CLI |
||||
MOV |
word ptr [BX], OFFSET NewFunc |
;设置中断处理程序的偏移量 |
||
MOV |
word ptr [BX 2], SEG NewFunc |
;设置中断处理程序的段地址 |
||
STI |
||||
…… |
在上面程序段中, 指令CLI是一条值得注意的指令,它用来确保随后二条MOV指令被连续执行而不被打断。这是因为执行其第一条MOV指令后,原中断向量表中的入口地址就被 破坏了,这时,该入口地址既不是指向原处理程序,也不指向新处理程序。如果此刻正巧发生了该类型的中断请求,那么,系统将转向一个非法的位置。如果程序员 能确信此时不会发生该类型的中断请求,当然也就不必插入关中断指令。
后面的指令STI是开中断指令,它允许CPU响应其后的中断请求。
3、修改中断向量的步骤
前面,分别介绍了读取和设置中断入口地址的方法。在编程的实际过程中,若要修改某个具体的中断处理程序时,一般需按下面几步来完成:
1)、读取指定中断的中断处理程序入口地址,并把它保存在存储单元内;
2)、把用户编写的程序段设置为指定中断的新处理程序;
3)、在用户程序结束之前(或不需要新的处理程序时),把步骤1保存的入口地址恢复成处理该中断的入口地址。
程序员按以上三步来编程,可保证:在其程序运行过程中,该指定的中断将按新的处理程序来处理,程序结束后,中断系统又恢复成原来的处理方式。所以,这种中断向量的改变对其它程序或使用者来说是透明的,当然也就不会影响它们的正常运作。
以上三步具体化的形式如下:
|
…… |
|||
INTNO |
EQU 40H |
;假设被修改的中断号 |
||
OldAddr |
DD ? |
|||
…… |
||||
NewFunc |
PROC |
;新的中断处理程序 |
||
NewFunc |
…… |
|||
IRET |
||||
ENDP |
||||
|
…… |
|||
MOV |
AL, INTNO |
|||
MOV |
AH, 35H |
|||
INT |
21H |
|||
MOV |
word ptr OldAddr, BX |
|||
MOV |
word ptr OldAddr 2, ES |
;步骤1:保存原入口地址 |
||
MOV |
DX, OFFSET NewFunc |
|||
MOV |
AX, SEG NewFunc |
|||
MOV |
DS, AX |
|||
MOV |
AL, INTNO |
|||
MOV |
AH, 25H |
|||
INT |
21H |
;步骤2:设置新的入口地址 |
||
…… ;用户编写的主要程序 …… |
||||
MOV |
DX, word ptr OldAddr |
|||
MOV |
DS, word ptr OldAddr 2 |
;本指令与上一条指令能交换吗? |
||
MOV |
AL, INTNO |
|||
MOV |
AH, 25H |
|||
INT |
21H |
;步骤3:恢复原入口地址 |
||
…… END |