我试图创建一个简单的游戏引擎/库来创建我自己的DOS游戏。我目前正在努力让输入正常工作。我遇到的问题是我的自定义ISR处理int 9(键盘输入)会锁定我的程序。
注意:我使用我的编译器_dos_getvect()和_dos_setvect();但是,我不知道为什么我自己的自定义getInterruptVector()和setInterruptVector()不起作用。如果有人可以解释原因,我将非常感激。
看看" interrupt_hooker.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;
}
#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
#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;
}
}
#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
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
}
}
答案 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位接近指针,不确定你的内存模型是什么。)