初始化IDT
(这里再次提醒,请一定通读和理解所有框架代码,否则很难完成任务!!!)
掌控全局
我们可以在idt.c里面看到IDT初始化函数:initIdt。
在这个文件里,我们发现有一个全局变量,是GateDescriptor数组,这就是我们至关重要的IDT。是否还记得下面这个图?前面基础知识部分讲过的。我们要根据这个结构填充setIntr函数和setTrap函数!
80386 INTERRUPT GATE
31 23 15 7 0
+-----------------+-----------------+---+---+---------+-----+-----------+
| OFFSET 31..16 | P |DPL|0 1 1 1 0|0 0 0|(NOT USED) |4
|-----------------------------------+---+---+---------+-----+-----------|
| SELECTOR | OFFSET 15..0 |0
+-----------------+-----------------+-----------------+-----------------+
80386 TRAP GATE
31 23 15 7 0
+-----------------+-----------------+---+---+---------+-----+-----------+
| OFFSET 31..16 | P |DPL|0 1 1 1 1|0 0 0|(NOT USED) |4
|-----------------------------------+---+---+---------+-----+-----------|
| SELECTOR | OFFSET 15..0 |0
+-----------------+-----------------+-----------------+-----------------+
这两个set函数传递的参数有如下几个:
ptr:门描述符的指针,可以通过它来访问对应的结构体!
selector:需要填充的选择子(注意!!!这里有坑,请回忆Selector的结构。我们在memory.h里帮你实现了两个宏KSEL和USEL)。
offset:与中断对应的处理函数地址(段内偏移)。
dpl:最后是DPL。硬件中断(即除了int指令之外的中断)不受DPL影响,8259A的15个中断都为内核级可以禁止用户程序用
int
指令模拟硬件中断!!!而syscall对应的门描述符的dpl......
我们看一下doirq.S里面的asmDoirq函数,会发现它有一个很奇怪的行为:把esp压进栈。
不要着急!注释里面说了:esp is treated as a parameter。那么是什么的参数呢?
对于Intr和Trap
很多同学对哪些中断设置成Intr,哪些设置成Trap会很有疑惑。
这里建议把keyboard设置成Intr,否则如果快速按键的话可能会出现连续中断嵌套的问题;同时syscall指令也可以设置成Intr,以防止被打断。其余均可设置成Trap。
对于键盘中断
要想加上键盘中断的处理,首先要在IDT表中加上键盘中断对应的门描述符,根据前文,8259a将硬件中断映射到键盘中断的向量号0x20
-0x2F
,键盘为IRQ1,所以键盘中断号为0x21
,框架代码也提供了键盘中断的处理函数irqKeyboard
。
Last updated