Sea*_*mey 1 c assembly dos game-engine
我正在尝试制作一个简单的游戏引擎/库来创建我自己的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;
}
Run Code Online (Sandbox Code Playgroud)
#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)
#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)
#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)
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)
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位指针,不确定你的内存模型是什么.)