保护模式安装描述由上一节的讨论得知,GDT是保护模式所必须的数据结构,那么我们在进入保护模式之前,必须设定好GDT,并通过LGDT将其装入相应的寄存器
尽管GDT允许被放在内存的任何位置,但由于GDT中的元素——描述符——都是64-bit长,也就是说都是8个字节,所以为了让CPU对GDT的访问速度达到最快,我们应该将GDT的入口地址放在以8个字节对齐,也就是说是8的倍数的地址位置
GDT中第一个描述符必须是一个空描述符,也就是它的内容应该全部为0
如果引用这个描述符进行内存访问,则是产生General Protection异常
如果一个OS不使用虚拟内存,段模式会是一个不错的选择
但现代OS没有不使用虚拟内存的,而实现虚拟内存的比较方便和有效的内存管理方式是页式管理
但是在IA-32上如果我们想使用页式管理,我们只能使用段页式——没有方法可以完全禁止段模式
但我们可以尽力让段的效果降低的最小
IA-32提供了一种被称作“Basic Flat Model”的分段模式可以达到这种效果
这种模式要求在GDT中至少要定义两个段描述符,一个用来引用Data Segment,另一个用来引用Code Segment
这2个Segment都包含整个线性空间,即Segment Limit = 4 GB,即使实际的物理内存远没有那么多,但这个空间定义是为了将来由页式管理来实现虚拟内存
在这里,我们只是处于启动阶段,所以我们只需要初步设置一下GDT,等真正进入保护模式,启动了OS Kernel之后,具体OS打算如何设置GDT,使用何种内存管理模式,由Kernel自身来设置,启动只需要给Kernel的数据段和代码段设置全部线性空间就可以了
段描述符的格式如下图所示:具体到代码段和数据段,它们的格式如下图所示:下面就是在启动阶段为进入保护模式而设置的临时的gdt
这里定义了3个段描述符:第一个是系统规定的空描述符,第2个是引用4 GB线性空间的代码段,第3个是引用4 GB线性空间的数据段
这是"Basic Flat Model"所要求的最下GDT设置,但就启动阶段,只是为了进入保护模式,并为内核提供一个连续的,最大的线性空间这个目的而言,已经足够了
# Descriptor tablesgdt:.word 0, 0, 0, 0 # dummy.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb).word 0 # base address = 0.word 0x9A00 # code read/exec.word 0x00CF # granularity = 4096, 386# (+5th nibble of limit).word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb).word 0 # base address = 0.word 0x9200 # data read/write.word 0x00CF # granularity = 4096, 386# (+5th nibble of limit)
以上内容由大学时代综合整理自互联网,实际情况请以官方资料为准。