idt_48:
.word 0
.word 0,0
idt表的基地址居然还是0x00000,这里就搞不懂了,因为这个时候0x00000的地方已经是system模块了,所以在真正的重新设置idt表以前,如果出现异常,我不知道系统将会进行什么样的处理,这里是问题一
setup.s会读取大量的参数然后存到0x90000处,也就是说会覆盖bootsect.s,具体的参数分布书上44页有,这里有个问题是,系统会将 第一个硬盘的参数表读到0x90080处,然后再读取第二个硬盘的参数表到0x90090处,然后再去检测到底有没有第二个硬盘,如果没有再将 0x90090处的参数表清0,怪了,为什么不先检测有没有第二个硬盘,在去决定是否读取参数表到0x90090呢?非要反着来不成?
下面是我对保护模式的一点理解,不知是否正确,有错误欢迎提出:
在16位的实模式下的程序在内存中的布局和操作系统的是混在一起的,也就是说,cpu没有提供对操作系统的保护,这会出很多问题,32为保护模式下, cpu提供的很强大的功能来保护操作系统的代码不被侵犯,我们所要做的就是提供相应的数据,将相应的寄存器初始化,打开A20地址线,然后执行一个跳转指 令,cpu就会进入保护模式,对我们的程序进行保护,具体的各位可以在网上找到资料,其中一个方法就是设置gdt以及ldt来保护操作系统以及应用程序, gdt(大小限制在64k以内)也即全局描述符表里包含有全局描述符,每个全局描述符得大小为8字节,所以理论上,一个gdt一共可以有64K/8=8K 个全局描述符.其中三个是描述全局性的操作系统的代码段,数据段,其他的一个程序占用一个全局描述符.
系统怎么来确定要使用哪一个全局描述符呢?使用段选择子!这里是他的结构:

其中3-15字节是用来索引gdt来去定某一个全局描述符得,共13位,所以gdt最大长度限制在2^13=64K.但是不知道为什么在这里Linus只将gdt的长度设置为了2K,也就是为什么在
gdt_48:
.word 0x800 !这里为什么是0x800,而不是0xFFFF,难道就是因为现在的gdt是临时的,以后还有设置,所以只要够现在用就可以了??
.word 512+gdt,0x9 ! 这里由于setup.s是在0x90200处,所以要加上0x200(512)的偏移量。
然后就是为系统进入32为保护模式作准备了,这里就要先初始化gdt,由于现在还没有程序运行,所以只是用了三项(其实是两项),其中,第零项没有使用,第一项描述系统的代码段,第二项描述系统的数据段(堆栈段)。
全局表述符表:
gdt:
.word 0x0000 !第0个弃用
.word 0x0000
.word 0x0000
.word 0x0000
.word 0x07FF !第1个,第0个用了4个word,所以这里偏移量是0x08
.word 0x0000 !用来描述系统代码段
.word 0x9A00
.word 0x00C0
.word 0x07FF !第2个,偏移量是0x10,也就是16
.word 0x0000 !用来描述系统数据段
.word 0x9200
.word 0x00C0
这里是gdt的结构

这是,进入保护模式所要准备的数据已经够了,接下来就是加载gdt的基地址以及大小限制到专用寄存器gdtr,idt基地址以及大小限制到idtr,然后打开A20数据线,关于A20数据线,哈工大纯c板块上有很好的文章介绍,然后重新对8259进行编程(看见头大,没怎么看),设置状态字,然后执行
jmpi 0,8 !这里的8就是上面的段选择子的值,化为二进制为 0000,0000,0000,1000 这里的1就是第1个全局描述符,即系统代码段,就会去执行head.s
最好对这个时候内核内存布局有个印象,便于以后的理解
-------------------
数据段表述符
-------------------
代码段描述符
-------------------
-------------------0X90200
硬件参数
-------------------0X90000
head.s程序
--------------------0X00000
没有评论:
发表评论