一 为什么要有保护模式
首先要明白,与保护模式不同的就是之前所说的实模式,既然有保护模式,就说明实模式某些方面无法满足我们的要求。以下是实模式的问题:
- 实模式下操作系统和用户程序属于同一特权级。
- 用户程序所引用的地址都是指向真实的物理地址,也就是说逻辑地址等于物理地址。
- 用户程序可以自由修改段基址,可以不亦乐乎地访问所有内存,没人拦得住。
- 访问超过64KB的内存区域时要切换段基址,转来转去容易晕乎。
- 一次只能运行一个程序,无法充分利用计算机资源。
- 共 20 条地址线,最大可用内存为 1MB,这即使在 20 年前也不够用。
1-3是安全性问题,4、5是使用方面的缺陷,6是硬伤。
二 全局描述符表
保护模式下,内存段不再是简单地用段寄存器加载一下段基址就能用,段信息增加了很多,需要提前把段定义好才能使用。全局描述符表( Global Descriptor Table, GDT)是保护模式下内存段的登记表。
段描述符
保护模式一大特点就是安全,内存段也会加上许多的安全属性。段描述符是放在内存中的,一个段描述符占8B,结构如下:

下面介绍一下段描述符内容:
低32位
- 段描述符的低32位分为两部分,前16位用来存储段的段界限的前 0~15位,后16位用来存储段基址的0~15位。
高32位
- 0~7位是段基址的 16~23,24~31 位是段基址的 24~31 位,加上在段描述符低32位中的段基址0~15位,凑齐32位基地址(这个布局是为了兼容16位机)
- 8~ 11 位是 type 字段 , 共 4 位,用来指定本描述符的类型。
- 12位是S字段,S 为 0 时表示系统段, S 为 1 时表示数据段(凡是硬件运行需要用到的东西都可称之为系统,凡是软件(操作系统也属于软件, CPU 眼中,它与用户程序无区别)需要的东西都称为数据)
- 段描述符的第 13~14 位是 DPL 字段, Descriptor Privilege Level,即描述符特权级。
- 段描述符的第 15 位是 P 字段, Present,即段是否存在。如果段存在于内存中, P 为 1,否则 P 为 0。
- 段描述符的第 16~ 19 位是段界限的第 16~ 19 位。
- 段描述符的第 20 位为 AVL 宇段,从名字上看它是 AVaiLable,可用的。
- 段描述符的第 21 位为 L 字段,用来设置是否是 64 位代码段。 L 为 1 表示 64 位代码段。
- 段描述符的第 22 位是 D/B 字段,用来指示有效地址(段内偏移地址)及操作数的大小。(兼容)
- 段描述符的第 23 位是 G 宇段, Granularity,粒度,用来指定段界限的单位大小。
全局描述符表GDT以及选择子
全局描述符表实际上就是段描述符数组,每一个段用一个下标来索引,这个下标就是选择子。
首先,查找全局描述符表需要用到GDTR寄存器,该寄存器有48位,只能用lgdt初始化该寄存器。GDTR寄存器内容如下:

前16位代表以字节位单位的界限值,2^16=65536字节。每个段描述符8字节,所以最多可容纳2^13=8192个段。
接下来,用选择子索引段描述符。段寄存器是16位,所以选择子也是16位。
- 选择子0~1位代表请求特权级,RPL。
- 2位代表TI位,用来代表是在GDT还是LDT中。
- 高13位代表下标,可索引8192个段。

注意:保护模式下都是32位地址线和寄存器,任一寄存器都可以访问全部内存,不需要段基址左移4位在和段内偏移地址相加,直接相加即可。
三 进入保护模式
进入保护模式的三个步骤:
- 构建全局描述符表
- 打开A20地址线(关闭地址回绕)
- CR0寄存器的第0位,PE(Protection Enable)位置为1,即打开保护模式
保护模式体现在哪?
向段寄存器加载选择子的保护
- 检查选择子TI,如果TI值为0,则从GDT中查找段,否则从LDT查找
- 拿到GDT基址和GDT界限值后,计算选择子中段是否越界,越界抛异常。(描述符表基地址+选择子中的索引值*8 + 7<=描述符表基地址+描述符表界限值)
- 拿到段描述符后检查段描述符type字段
- 检查段描述符P字段
- 加载选择子到段寄存器
代码段和数据段、栈段保护
通过段描述符计算段内偏移地址是否越界,越界抛异常。

浙公网安备 33010602011771号