C(DOS)中的嵌入式汇编 - 非法指令

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寄存器的内容.我不能继续这个计划.有什么建议?

Ale*_*nze 8

你正在做的事情有多种原因:

  1. 常规C函数不能安全地用作中断服务程序,因为它们无法正确保存,加载和恢复CPU寄存器.必须使用interrupt关键字声明它们.最后他们会iret帮你的.
  2. 可以从中断例程异步地在程序中更改的变量必须声明为volatile,否则您可能会被编译器错误地优化访问它们.
  3. 内联汇编代码可能会破坏CPU寄存器的内容.这段代码的一个问题是你的asm块会混乱堆栈指针.第一个块退出,堆栈上有几个额外的单词.这对编译器来说可能完全出乎意料,可能会破坏您的程序.可能还有其他问题,但我不打算用编译器文档检查哪些寄存器必须由内联汇编块保存.我完全避免这样做,setvect()而是选择功能.
  4. 从中断服务例程中调用大多数标准库函数会产生麻烦,因为这些函数通常不是可重入/线程安全的.他们可以以完全意想不到的方式修改一些全局变量或状态,以用于程序的其余部分.从中断服务程序(你的printf()依赖,btw)调用DOS服务函数也是如此.你只能在DOS说它没问题时调用它们.它通过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)

  • @Mikael:享受. (2认同)