簡體   English   中英

C(DOS)中的嵌入式匯編 - 非法指令

[英]Embedded assembly in C (DOS) - illegal instruction

我正在嘗試重新編程指令向量表。 這是我使用的代碼:

#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寄存器的內容。 我不能繼續這個計划。 有什么建議么?

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

  1. 常規C函數不能安全地用作中斷服務程序,因為它們無法正確保存,加載和恢復CPU寄存器。 必須使用interrupt關鍵字聲明它們。 最后他們會為你而iret
  2. 可以從中斷例程異步地在程序中更改的變量必須聲明為volatile ,否則您可能會被編譯器錯誤地優化對它們的訪問。
  3. 內聯匯編代碼可能會破壞CPU寄存器的內容。 這段代碼的一個問題是你的asm阻塞堆棧指針。 第一個塊退出,堆棧上有幾個額外的單詞。 這對編譯器來說可能完全出乎意料,可能會破壞您的程序。 可能還有其他問題,但我不打算用編譯器文檔檢查哪些寄存器必須由內聯匯編塊保存。 我完全避免這樣做,而是選擇setvect()函數。
  4. 從中斷服務例程中調用大多數標准庫函數會產生麻煩,因為這些函數通常不是可重入/線程安全的。 他們可以以完全意想不到的方式修改一些全局變量或狀態,以用於程序的其余部分。 從中斷服務程序(你的printf()依賴,btw)調用DOS服務函數也是如此。 你只能在DOS說它沒問題時調用它們。 它是通過InDos標志變量實現的,但是當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
    }
}
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}
}

此函數已設置您未正確銷毀的堆棧框架。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM