我正在尝试重新编程指令向量表。这是我使用的代码:
#include <stdio.h>
int a=1;
void func();
void keyboard()
{
printf("\n\nkeyboard!!!\n");
a=0;
asm{iret}
}
int main ()
{
printf("starting...");
func();
return 0;
}
int vectorcs = 0;
int vectorip = 0;
void func()
{
printf("\n*****\n");
asm{
cli
mov ax,0
mov es,ax
mov bx,36
mov ax,word ptr es:[bx]
mov vectorip,ax
push ax
mov ax,word ptr es:[bx+2]
mov vectorcs,ax
push ax
mov ax,cs
mov word ptr es:[bx],offset keyboard
mov es:[bx+2],ax
sti
}
printf("\n%d %d\n",vectorip,vectorcs);
while (a) {
}
asm {
cli
mov es,bx
mov bx,36
pop ax
mov word ptr es:[bx+2],ax
}
asm{
pop ax
mov word ptr es:[bx],ax
sti
}
}
我正在使用Turbo C ++ 3.0 当我尝试运行该程序时,“16位MS-DOS子系统:NTVDM CPU遇到了非法指令。”出现。然后它显示CS,OP和IP寄存器的内容。我不能继续这个计划。有什么建议吗?
答案 0 :(得分:8)
由于多种原因,您正在做的事情不正确:
interrupt
关键字声明它们。他们最后会为你iret
。volatile
,否则您将面临编译器错误优化访问它们的风险。asm
块会使堆栈指针混乱。第一个块退出,堆栈上有几个额外的单词。这对编译器来说可能完全出乎意料,可能会破坏您的程序。可能还有其他问题,但我不打算用编译器文档检查哪些寄存器必须由内联汇编块保留。我完全避免这样做,而是选择setvect()
功能。InDos
标志变量完成的,但是,当InDos
= 0时,并非所有人都可以安全地调用。在this question的答案中,了解如何更改中断向量,定义中断服务程序以及从中调用DOS函数,所有这些都使用Turbo C。
您可能还会发现this question及其答案很有用。
修改强>:
如果没有dos.h的内联asm功能,你可以这样做:
#include <stdio.h>
volatile int a = 1;
void interrupt (*pOldInt9)(void);
void func(void);
void interrupt keyboard(void)
{
printf("\n\nkeyboard!!!\n");
asm {
in al, 0x60
in al, 0x61
mov ah, al
or al, 0x80
out 0x61, al
mov al, ah
out 0x61, al
}
a = 0;
asm {
mov al, 0x20
out 0x20, al
}
}
int main(void)
{
printf("starting...");
func();
return 0;
}
void func(void)
{
printf("\n*****\n");
asm {
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, es:[bx]
mov word ptr pOldInt9, ax
mov word ptr es:[bx], offset keyboard
mov ax, es:[bx + 2]
mov word ptr pOldInt9[2], ax
mov es:[bx + 2], cs
sti
pop es
pop bx
}
while (a) {}
asm {
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, word ptr pOldInt9
mov es:[bx], ax
mov ax, word ptr pOldInt9[2]
mov es:[bx + 2], ax
sti
pop es
pop bx
}
}
答案 1 :(得分:1)
asm {
cli
mov es,bx
mov bx,36
pop ax
mov word ptr es:[bx+2],ax
}
该代码之前bx
包含哪些内容?
void keyboard()
{
printf("\n\nkeyboard!!!\n");
a=0;
asm{iret}
}
此函数设置了一个未正确销毁的堆栈帧。