Mik*_*ael 3 c assembly dos inline-assembly
我正在尝试重新编程指令向量表.这是我使用的代码:
#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
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Turbo C++ 3.0当我尝试运行这个程序时,"16位MS-DOS子系统:NTVDM CPU遇到了非法指令." 出现.然后它显示CS,OP和IP寄存器的内容.我不能继续这个计划.有什么建议?
你正在做的事情有多种原因:
interrupt关键字声明它们.最后他们会iret帮你的.volatile,否则您可能会被编译器错误地优化访问它们.asm块会混乱堆栈指针.第一个块退出,堆栈上有几个额外的单词.这对编译器来说可能完全出乎意料,可能会破坏您的程序.可能还有其他问题,但我不打算用编译器文档检查哪些寄存器必须由内联汇编块保存.我完全避免这样做,setvect()而是选择功能.InDosflag变量完成,但是,当InDos= 0 时,并非所有都可以安全地调用.了解如何更改中断向量,定义中断服务程序,并从中调用DOS功能,全部采用Turbo C,在回答这个问题.
您可能还会发现此问题及其答案有用.
编辑:
如果没有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
}
}
Run Code Online (Sandbox Code Playgroud)