我的汇编代码在保护模式下,实现了一个键盘中断响应函数。
这个函数很简单,就是在屏幕上显示一个字符串,然后返回。我预期的效果是每按一次键,屏幕上就会在上一个字符串的下一行显示相同的一个字符串。
但是程序运行起来之后,只能响应一次键盘输入(只显示出一个字符串),之后的键盘输入都不能响应。这是为什么呢?
我的键盘中断响应函数是这样的:
;键盘中断处理(汇编文件)
extern key_interrupt
key_int:
;key_int这个汇编函数调用C语言文件中的key_interrupt函数
call key_interrupt
iretd
//下面是C语言文件中的函数
void key_interrupt()
{
disp_str("Key Pressed\n");
}
;内核文件是这样的(有些代码省略了)
_start:
.......
call cstart;在这个函数里面初始化IDT
;加载idt
lidt [idt_ptr]
sti
hlt
------解决方案--------------------------------------------------------
每次中断程序完成后需要发一个EOI信号给8259A中断控制器,以便继续接收下一个中断!
mov al, 020h ; 中断复位
out 020h, al
------解决方案--------------------------------------------------------
- Assembly code
_@Int21: call _@Ksave in al, 021h ; 将键盘中断屏蔽,在此过程中不再响应键盘中断 or al, (1<<1) out 021h, al mov al, 020h ; 中断复位,其他中断可继续 out 020h, al sti ; 置中断屏蔽位, 继续响应外部中断 ; ////////////////////////////////////////////// ; 中断处理过程 call _@KeyInScan ; ////////////////////////////////////////////// cli ; 清中断屏蔽位, 暂停响应外部中断 in al, 021h ; 将键盘中断打开 and al, ~(1<<1) out 021h, al ret
------解决方案--------------------------------------------------------
注意!iret 返回在 _@Ksave 代码中,返回地址入栈了,这里ret返回时正好是 _@Ksave 中调用_@Int21下一句。iret返回时自动打开中断。