Dos中断处理程序锁定程序

时间:2017-01-02 23:43:27

标签: c assembly game-engine dos

我试图创建一个简单的游戏引擎/库来创建我自己的DOS游戏。我目前正在努力让输入正常工作。我遇到的问题是我的自定义ISR处理int 9(键盘输入)会锁定我的程序。

注意:我使用我的编译器_dos_getvect()和_dos_setvect();但是,我不知道为什么我自己的自定义getInterruptVector()和setInterruptVector()不起作用。如果有人可以解释原因,我将非常感激。

看看" interrupt_hooker.c"对于有问题的代码。

的main.c

#include "input.h"
#include "stdio.h"

int main(int argc, char *argv[])
{
    hookKeyboardISR();

    unsigned char i = 0;

    while(1)
    {
        printf("%i", 1);
        //i = getKey(SCAN_ESC);
        //printf("%i", i);
    }

    unhookKeyboardISR();
    return 0;
}

input.h

#ifndef INPUT_H_INCLUDED
#define INPUT_H_INCLUDED

#include "scan_codes.h"

void            hookKeyboardISR();
void            unhookKeyboardISR();

unsigned char   getKey(unsigned char scan_code);

unsigned char   isExtended();

#endif // INPUT_H_INCLUDED

Input.c中

#include "input.h"
#include "interrupt_hooker.h"

#ifndef NULL
#define NULL ((void*)0)
#endif // NULL

unsigned char key_array[MAX_SCAN_CODES] = {0};
unsigned char extended_key = 0;

void __interrupt (*oldKeyboardISR)() = NULL;


unsigned char getKey(unsigned char scan_code)
{
    return key_array[scan_code];
}

unsigned char isExtended()
{
    return extended_key;
}

void __interrupt keyboardISR()
{
    unsigned char scan_code = 0;

    unsigned char temp = 0;
    scan_code = inp(0x60);
    outp(0x61,(temp = inp(0x61)) | 0x80);
    outp(0x61,temp);
    /*asm
    {
        in  al, 60h         //get scan code from keyboard controller
        mov scan_code, al   //put it in scan_code

        in  al, 61h
        or  al, 80h
        out 61h, al
        xor al, 80h
        out 61h, al
    }*/

    switch(scan_code)
    {
    //if extended code
    case 0xe0:
        extended_key = 1;
        break;

    case 0xe1:
        break;

    default:
        //check if break code
        if(scan_code & 0x80){
            scan_code &= 0x7f;

            //set key to released
            key_array[scan_code] = 0;

        }
        else{
            //set key to pressed
            key_array[scan_code] = 1;
        }

        extended_key = 0;
        break;
    }

    //send EOI
    outp(0x20, 0x20);
    /*asm
    {
        sti
        mov al, 20h
        out 20h, al
    }*/
}

void hookKeyboardISR()
{
    if(oldKeyboardISR == NULL){
        getInterruptVector(0x09, oldKeyboardISR);
        setInterruptVector(0x09, keyboardISR);
    }
}

void unhookKeyboardISR()
{
    if(oldKeyboardISR != NULL){
        setInterruptVector(0x09, oldKeyboardISR);
        oldKeyboardISR = NULL;
    }
}

interrupt_hooker.h

#ifndef INTERRUPT_HOOKER_H_INCLUDED
#define INTERRUPT_HOOKER_H_INCLUDED

void getInterruptVector(unsigned char int_number, void __interrupt (*isr)());

void setInterruptVector(unsigned char int_number, void __interrupt (*isr)());

#endif // INTERRUPT_HOOKER_H_INCLUDED

interrupt_hooker.c

void getInterruptVector(unsigned char int_number, void __interrupt (*isr)())
{
    asm
    {
        cli
        mov al, int_number
        mov ah, 35h
        int 21h

        mov word ptr [isr], bx
        mov word ptr [isr+2], es
        sti
    }
}

void setInterruptVector(unsigned char int_number, void __interrupt (*isr)())
{
    asm
    {
        cli
        mov dx, word ptr [isr+2]
        mov ds, dx
        mov dx, word ptr [isr]

        mov al, int_number
        mov ah, 25h
        int 21h
        sti
    }
}

1 个答案:

答案 0 :(得分:5)

mov dx, word ptr [isr]可能会尝试使用你刚刚破坏的ds,除非isr被解析为bp+offset,在这种情况下它会使用ss,而且应该是好。另外,我想编译器不会对您销毁ds感到高兴。

更安全的代码可能是:

cli
push ds
mov al, int_number
mov ah, 25h
mov dx, word ptr [isr]
mov ds, word ptr [isr+2]
int 21h
pop ds
sti

您的getInterruptVector因为错过了间接级别而被破坏了 - 您只是修改了C中按值传递的参数。您必须将其作为{{\ n}来调用它{1}}(请注意getInterruptVector(0x09, &oldKeyboardISR);),当然还要在功能中取消引用它,例如:

&

(假设16位接近指针,不确定你的内存模型是什么。)