Dos中断处理程序锁定程序

Sea*_*mey 1 c assembly dos game-engine

我正在尝试制作一个简单的游戏引擎/库来创建我自己的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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*ter 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
Run Code Online (Sandbox Code Playgroud)

getInterruptVector被打破是因为它缺少一个间接级别 - 你只是修改了C中传递值的参数.你必须调用它作为getInterruptVector(0x09, &oldKeyboardISR);(注意&)并且当然在你的函数中取消引用它,类似于:

    mov al, int_number
    mov ah, 35h
    int 21h

    mov di, word ptr [isr]
    mov [di], bx
    mov [di+2], es
Run Code Online (Sandbox Code Playgroud)

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