上两篇文章,【从头开始写操作系统系列】实现一个-GDT(1)、【从头开始写操作系统系列】实现一个-GDT(2),主要介绍了段描述符结构以及实现和选择子结构。这篇文章,我们结合之前所述,对 GDT 做一个总结。
#全局描述符表(GDT)
全局描述符表是在保护模式下才用到的结构。在整个系统中,全局描述符表只有一张,可以放在内存的任何位置,但是CPU必须知道它的入口地址,也就是其基地址(Base),Intel 处理器的设计者专门设计了一个寄存器用于存放该地址,叫GDTR。程序员将 GDT 设置于内存的某个位置之后,通过 lgdt 指令将其入口地址放于 GDTR 中,之后,CPU 会根据该寄存器的值来访问 GDT。
- GDTR 结构如下图:
#段选择子(Selector)
在上一篇文章中我们已经知道,我们是通过段描述符在段描述符表中的位置来进行访问段描述符的。段选择子就是这样的一个16位的标识符,它标识了段描述符在段描述符表中的位置。
我们来看一下段选择子的结构:
索引:表示所需要的段在 GDT 中的位置
TI:引用描述符表指示位。
- TI = 0,表示从全局描述符表中读取描述符
- TI = 1,表示从局部描述符表中读取描述符
RPL:请求特权级,用于特权检查,占用两位,共有4级。
- 说明:任务中的每一个段都有一个特权级,每当程序想要访问一个段时,要将该程序所拥有的特权级与要访问的段特权级进行比较,来决定是否能访问该段。系统规定,CPU 只能访问同一特权级或较低特权级的段。
我们来举一个例子:
将逻辑地址(21h:12345678h)转换为线性地址。
选择子(21h)
SEL = 21h = 0000000000100 0 01
INDEX = 0000000000100, TI = 0, RPL = 01
表示:从 GDT 中读取第4个(0100b)描述符,特权级为01
偏移量(12345678h)
线性地址 = 12345678h + GDT 中第4个描述符的基地址(Base)
#局部描述符表(LDT)
局部描述符表(LDT)在系统中可以有若干张,一个任务可以有一张。LDT 和 GDT 在本质上是相同的,LDT 嵌套在 GDT 中。LDTR 记录 LDT 的起始地址,其中的内容是一个选择子,LDTR 在程序中可以通过 lldt 指令随时改变。由于 LDT 也是一段内存,也是一个段,因此同样需要一个描述符描述它,这个描述符存在于 GDT 中,并且这个描述符也对应一个选择子,LDTR 中存放的就是这个选择子。
具体结构如图:
我们再来举一个例子:
在表LDT2中选择第三个描述符所描述的段的地址12345678h
首先,装载 LDTR 使其指向 LDT2,使用 lldt 指令将 Selector2装载至 LDTR
通过逻辑地址(SEL:OFFSET),将 SEL 的 Index = 3(选择第三个描述符),TI = 1(在 LDT 读取描述符),OFFSET = 12345678h,因此逻辑地址为:(1C:12345678h)
由 SEL 选择出相应的段描述符,段描述符中的基地址(Base)+ OFFSET 即为线性地址。
#总结
这篇文章,我们介绍了一下局部描述符表,并且复习和补充了关于 GDT 的知识。现在,我们了解了 GDT,GDT 是系统进入保护模式必备的结构。因此,接下来我们会进入保护模式的世界。后边的文章将会讨论,系统是怎么从实模式跳转到保护模式的。
版权声明:本文为博主原创文章,未经博主允许不得转载。