Dos 中断处理程序锁定程序
Dos Interrupt Handler Locks Up Program
我正在尝试制作一个简单的游戏 engine/library 来创建我自己的 DOS 游戏。我目前正在努力让输入正常工作。我遇到的问题是我处理 int 9(键盘输入)的自定义 ISR 锁定了我的程序。
注意:我通过使用编译器的 _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
}
}
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 中按值传递的参数。您必须将其调用为 getInterruptVector(0x09, &oldKeyboardISR);
(注意 &
),当然在你的函数中取消引用它,比如:
mov al, int_number
mov ah, 35h
int 21h
mov di, word ptr [isr]
mov [di], bx
mov [di+2], es
(假设是 16 位 near 指针,不确定您的内存模型是什么。)
我正在尝试制作一个简单的游戏 engine/library 来创建我自己的 DOS 游戏。我目前正在努力让输入正常工作。我遇到的问题是我处理 int 9(键盘输入)的自定义 ISR 锁定了我的程序。
注意:我通过使用编译器的 _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
}
}
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 中按值传递的参数。您必须将其调用为 getInterruptVector(0x09, &oldKeyboardISR);
(注意 &
),当然在你的函数中取消引用它,比如:
mov al, int_number
mov ah, 35h
int 21h
mov di, word ptr [isr]
mov [di], bx
mov [di+2], es
(假设是 16 位 near 指针,不确定您的内存模型是什么。)