->
setup.s会将被bootsect.s读取到0×10000处的system模块移动到0×00000处,这样好象会把中断表给覆盖掉,文件执行到后来会加载中断描述符表,但是idt表却是这个样子的:
idt_48:
.word 0
.word 0,0
idt表的基地址居然还是0×00000,这里就搞不懂了,因为这个时候0×00000的地方已经是system模块了,所以在真正的重新设置idt表以前,如果出现异常,我不知道系统将会进行什么样的处理,这里是问题一
setup.s会读取大量的参数然后存到0×90000处,也就是说会覆盖bootsect.s,具体的参数分布书上44页有,这里有个问题是,系统会将 第一个硬盘的参数表读到0×90080处,然后再读取第二个硬盘的参数表到0×90090处,然后再去检测到底有没有第二个硬盘,如果没有再将 0×90090处的参数表清0,怪了,为什么不先检测有没有第二个硬盘,在去决定是否读取参数表到0×90090呢?非要反着来不成?
下面是我对保护模式的一点理解,不知是否正确,有错误欢迎提出:
在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 0×800 !这里为什么是0×800,而不是0xFFFF,难道就是因为现在的gdt是临时的,以后还有设置,所以只要够现在用就可以了??
.word 512+gdt,0×9 ! 这里由于setup.s是在0×90200处,所以要加上0×200(512)的偏移量。
然后就是为系统进入32为保护模式作准备了,这里就要先初始化gdt,由于现在还没有程序运行,所以只是用了三项(其实是两项),其中,第零项没有使用,第一项描述系统的代码段,第二项描述系统的数据段(堆栈段)。
全局表述符表:
gdt:
.word 0×0000 !第0个弃用
.word 0×0000
.word 0×0000
.word 0×0000
.word 0x07FF !第1个,第0个用了4个word,所以这里偏移量是0×08
.word 0×0000 !用来描述系统代码段
.word 0x9A00
.word 0x00C0
.word 0x07FF !第2个,偏移量是0×10,也就是16
.word 0×0000 !用来描述系统数据段
.word 0×9200
.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
No Comments Now!
Be the first to comment on this entry.