Separated compilation and Interrupt handling
Setting GDT and IDT
1 | GDT Register : 48 bits |
1 | ;supplyment to naskfunc.nas |
Init PIC(Program Interrupt Controller)
Here is where the 8259A come !
- IRQ stands for Interrupt Request
- The CPU can only accept 1 interrupt at a time, since there is only one pin !
1 | //source of int.c |
ICW1和ICW4与PIC主板配线方式、中断信号的电气特性等有关,所以就不详细说明了。电脑上设定的是上述程序所示的固定值,不会设定其他的值。如果故意改成别的什么值的话,早期的电脑说不定会烧断保险丝,或者器件冒烟;最近的电脑,对这种设定起反应的电路本身被省略了,所以不会有任何反应。
电路上,+5V与GND(地)短路时,就会发生保险丝熔断、器件冒烟的现象。这可不是吓唬你,而是真的会发生.
Since CPU only has one interrupt pin, how can it know the interrupt number ?
中断发生以后,如果CPU可以受理这个中断,CPU就会命令PIC发送2个字节的数据。
这2个字节是怎么传送的呢?CPU与PIC用IN或OUT进行数据传送时,有数据信号线连在一起。PIC就是利用这个信号线发送这2个字节数据的。送过来的数据是“0xcd 0x??”这两个字节。
由于电路设计的原因,这两个字节的数据在CPU看来,与从内存读进来的程序是完全一样的,所以CPU就把送过来的“0xcd 0x??”作为机器语言执行。这恰恰就是把数据当作程序来执行的情况。
这里的0xcd就是调用BIOS时使用的那个INT指令。我们在程序里写的“INT 0x10”,最后就被编译成了“0xcd 0x10”。所以,CPU上了PIC的当,按照PIC所希望的中断号执行了INT指令
Why why int number is not start from 0x00 ?
这次是以INT 0x20
0x2f接收中断信号IRQ015而设定的。这里大家可能又会有疑问了。“直接用INT 0x00~0x0f就不行吗?这样与IRQ的号码不就一样了吗?为什么非要加上0x20?”是这样的,INT 0x00~0x1f不能用于IRQ,仅此而已。
之所以不能用,是因为应用程序想要对操作系统干坏事的时候,CPU内部会自动产生INT 0x00~0x1f,如果IRQ与这些号码重复了, CPU就分不清它到底是IRQ,还是CPU的系统保护通知。
Interrupt handler
keyboard : IRQ1 , mouse : IRQ12
1 | // int.c |
In order to return from interrupt handler, iretd
instruction must be used, so we need assembly here
1 | ;naskfunc.nas |
Then write the function to IDT
1 | set_gatedesc(idt+0x21 , (int)asm_inthandler21 , 2<<3 , AR_INTGATE32); |