30天自制操作系统笔记(第六天)
首先要讲讲GDT和IDT,前者是全局段号记录表,后者是中断记录表。
在操作系统,中断和分段是非常重要的东西,值得一提的是,计算机在未装系统之前,内存中最靠前那一段是中断记录表,但是这个机器本身带来的中断记录表功能比较少,因此操作系统会将其删除,并新建中断向量表。分段,实际上是操作系统管理内存的一种需求,因为操作系统往往需要将很多进程载入到内存中,用分段的方法,将进程的装载地址记录下来,就能在切换进程的时候快速找到其位置,然后执行,进程管理自然也是依赖于此。
那么,如何设置GDT和IDT呢?
GDT的设置,有两步,第一步是将目标内存区域内容清0,这个好办,第二步是将指定段上限和地址值赋值给名为GDTR的48位寄存器。四十八位,也就是6个字节,先用汇编写出装载GDT的函数
_load_gdtr: ;void load_gdtr(int limit,int addr) MOV AX,[ESP+4] MOV [ESP+6],AX LGDT [ESP+6] RET
这个汇编函数咋一看怪怪的,实际上只是对输入内容进行一个位数的调整,两个int均占四个字节,一共八个字节,有两个字节是不需要的,limit中的高位实际上是0,因为段地址是两个字节的,所以,这里的操作是把段地址这两个字节移到[ESP+6][ESP+7]上,这样,和后面的四个字节就能拼成六个字节。汇编这东西,果然繁琐!
举个例子吧,如果传入的参数分别为limit=0xffff,addr=0x00270000,由于低位存放在内存地址更小的字节里,内存里的顺序:
ff ff 00 00 00 00 27 00;
经过GDT函数调用后,变成:
00 00 ff ff 00 00 27 00;
当然实际上可以在传参的时候就把参数倒着写,不过这就更容易写错了,自然是输入正常顺序的数进去比较合理。这里LGDT的意思自然是把这个地址后面的六个字节传入寄存器,这就设置完成了。
中断记录表的设置和全局段号记录表类似,这里就不细说。
鼠标的移动会触发中断,通过编写对应的中断函数可以实现鼠标在屏幕上的实时显示,而要实现这整个过程,要做两步,首先编写中断函数,然后将这个函数注册到IDT中去。