real mode protected mode and segmentation
前言
在操作系统启动时,会先进入实模式(Real Mode),然后再转换为保护模式(Protected Mode),为什么需要这么做?两种模式的寻址方式有何不同?本文通过Intel 8086和Intel 80286分段寻址的不同来解释这两种模式的区别。
Intel 8086
8086被设计为完全的16位处理器,所有的内部寄存器、内部及外部数据总线都是16位宽,不过它具有20位宽的外部地址总线,这意味着它能够寻址2^20=1,048,576个地址,也就是最大能够支持1MB的寻址空间。这里可能会有疑问,刚才不是说8086是16位处理器吗?怎么能够进行20位地址总线寻址呢?这是由于8086处理器支持分段机制(Segmentation),它能够通过16 * Segment + Offset的方式进行寻址,例如Segment为0xf000,Offset为0xfff0,则进行如下转换:
16 * 0xf000 + 0xfff0
= 0xf0000 + 0xfff0
= 0xffff0
Segment为16位的基地址被存储在段寄存器(Segment Registers),Offset也同样为16位的偏移地址,通过左移位的方式组合得到的结果0xffff0称之为线性地址(Linear Address),可以理解为Segment为一个内存区域,Offset为相对于这个内存区域起始地址的偏移量。这时有的人可能会问了,如果Segment为0xffff且Offset为0xffff,通过上述公式计算:
16 * 0xffff + 0xffff
= 0xffff0 + 0xffff
= 0x10ffef
最终结果为0x10ffef,这已经超过20位地址总线的寻址范围(至少得24位地址总线才能够寻址此地址),这时CPU会丢弃最高位,实际访问的地址为0xffef(这也是在使用更大的内存地址空间前启用A20总线的原因,既启用高位地址)。这种直接能够访问内存地址的方式称之为实模式(Real Mode)。
Intel 80286
当80286问世时,外部地址总线被拓宽到24位,使得它的寻址能力进一步提升,但是它所带来的不仅仅是寻址能力的提升,还有一个新东西:保护模式(Protected Mode)。保护模式下的分段机制与实模式下的分段机制有些许不同,它通过以下数据结构进行段翻译(Segment Translation):
描述符(Descriptor)用来存储分段信息描述符表(Descriptor Table)有描述符所组成的数组结构段选择器(Selector)从描述符表中找到具体的某个描述符
虽然80286的段寄存器(Segment Registers)依然是16位,但是它保存的不再是段基地址,而是称之为Selector的选择器,这与实模式下的分段机制有所不同。保护模式下每个分段信息是存储在对应的Descriptor中,那么我们要进行地址转换则需要先在Descriptor Table中找到这个Descriptor,这就需要Selector,通过Selector定位到Descriptor,然后翻译Segment成为线性地址(Linear Address):

Descriptor
先看下Descriptor,它是由8-byte组成的数据结构:

段基地址(Base Address)- 由三个片段组成占用32位,用来表示地址的开始位置(后续配合
Offset来得到一个具体的地址)
- 由三个片段组成占用32位,用来表示地址的开始位置(后续配合
Segment Limit- 由两个片段组成占用20位,这两用来表示地址范围
G=Granularity- 如果清除,
Segment Limit单位为bytes最大能够表示2^20bytes - 如果设置,表示以
4KB(页大小)为单位,最大可表示2^32bytes
- 如果清除,
D=Default operand size- 如果清除,则为16位代码段
- 如果设置,则为32位
B=Big- 如果设置,则数据段的最大偏移量增加到32位
0xffffffff - 否则为最大16位
0x0000ffff,与D基本相同
- 如果设置,则数据段的最大偏移量增加到32位
L=Long- 如果设置,则为64位段(
D必须为零),并且该段中的代码使用64位指令编码 - 不能将
L与D或B同时设置
- 如果设置,则为64位段(
AVL=Available- 仅供软件使用,硬件不做处理
P=Present- 如果清除,则对此段的任何引用都会生成“段不存在”异常
DPL=Descriptor privilege level- 访问此描述符所需的特权级别
Type- 如果设置,则为代码段描述符。如果清除,则为数据/堆栈段描述符
C=Conforming- 可以从特权级别较低的级别调用此段中的代码
E=Expand-Down- 如果清除,则该段将从基地址扩展到基数+限制
- 如果设置,它将从最大偏移向下扩展到限制,这是通常用于堆栈的行为
R=Readable- 如果清除,则该段可以执行但不能读取
W=Writable- 如果清除,则可以读取但不能写入数据段
A=Accessed- 当访问该段时,该位由硬件设置为1,并由软件清除
由描述符的数据结构可以看出,它包含了段信息以及权限等信息,在程序将Selector加载到段寄存器中时,CPU不仅加载段的基地址,而且加载保护信息,根据这些信息对段内存进行保护,所以称之为保护模式(Protected Mode)。
未完待续...