各位C程序员大大们请进...急!!
偶在学习DOS6.22 下的TSR,开发工具为TC3.0,请教高手们一个问题:
怎么做才可以接管21H中断?常规方法好象是不行的,一运行就死机/花屏。。
方法一:
#include <dos.h>
typedef void interrupt ( *TInt )();
TInt Old21 = 0;
void interrupt MyInt21()
{
// ....
( *Old21 )();
}
void install () /*安装中断*/
{
disable();
setvect( 0x21, MyInt21 );
enable();
}
int main()
{
OldInt = getvect( 0x21 );
install();
keep(0,_SS+_SP/16-_psp);
return 0;
}
方法二:
#include <dos.h>
typedef void interrupt ( *TInt )();
typedef int far *FPInt;
FPInt MySeg = 0;
FPInt MyOff = 0;
TInt OldInt = NULL;
FPInt Vect21 = NULL;
void interrupt MyInt21()
{
// ....
( *OldInt )();
}
void install () /*安装中断*/
{
disable();
MyOff = ( fpint )MyInt21;
MySeg = ( fpint )_cs;
vect21 = MK_FP( 0x00, 4 * 0x21 ); // vector 21h
*vect21++ = myint21;
*vect21 = MySeg ;
//*vect21 = mk_fp( myseg, myoff );
enable();
}
int main()
{
OldInt = getvect( 0x21 );
install();
keep(0,_SS+_SP/16-_psp);
return 0;
}
问题: 这两种做法替换14H中断时,都没问题,但21H就不行,请问大家在替换INT21时需要注意哪些事情?21H是系统中断,我刚刚接触这方面,不是很懂,请大家多多帮忙!
[解决办法]
1.工程使用Large内存模式,或者
2.加上far修饰:
typedef void (interrupt far *TInt)();
void interrupt far MyInt21() {...}
如果还不行,把编译器产生的汇编代码中的MyInt21函数部分发出来我看看。
[解决办法]
在原中断返回后你的程序也不能破坏现场应立即返回给原始调用者,也就是说
:0001.0369 50 PUSH AX
:0001.036A 53 PUSH BX
:0001.036B 51 PUSH CX
:0001.036C 52 PUSH DX
:0001.036D 06 PUSH ES
:0001.036E 1E PUSH DS
:0001.036F 56 PUSH SI
:0001.0370 57 PUSH DI
:0001.0371 55 PUSH BP
:0001.0372 2E8B2E6503 MOV BP, CS:[0365]
:0001.0377 8EDD MOV DS, BP
:0001.0379 8BEC MOV BP,SP
:0001.037B 9C PUSHF
:0001.037C FF1E620D CALL FAR WORD PTR [0D62]
:0001.0380 50 PUSH AX
:0001.0381 B88219 MOV AX, 1982
:0001.0384 58 POP AX
:0001.0385 5D POP BP
:0001.0386 5F POP DI
:0001.0387 5E POP SI
:0001.0388 1F POP DS
:0001.0389 07 POP ES
:0001.038A 5A POP DX
:0001.038B 59 POP CX
:0001.038C 5B POP BX
:0001.038D 58 POP AX
:0001.038E CF IRET
的倒数的二行pop ax已经破坏了原中断的返回值