背景知识
以下说的知识皆以如非特别表明,皆说的是80386CPU
- 它的可寻址能力达到4GB
- 通过寄存器是32位
通用寄存器是32位的,2的32次方等于4GB,就可以使用一个通用寄存器来寻址,从而不必分段。虽然在地址上不再有分段的限制问题。但是,一个地址否可以被写入,可以被多少优先级的代码写入?等问题就出来,要解决此类问题,必须要在地址空间定义一些安全属性。这是由段选择器就有了作用。但是涉及属性和保护模式下段的其他参数和要表示的信息太多,要用64位的数据才能表示。
80386的段寄存器是16位的,无法放下保护模式下64位的段描述符。所以就把所有段的段描述符顺序放在内存中指定的位置,组成一个段描述符表(Descriptor Table
);而段寄存器中的16位用来索引信息,指定这个段的属性用段描述符表中的第几个描述符来表示。可以通过它在段描述符表中"选择"一个项目以得到段的全部信息。这时段寄存器中的信息不再是段地址,而是一个指向段描述符表的索引值,段描述符表中存着我们的地址等信息。此时我们称寄存器为,段选择器。
GTDTR
,是一个48位的寄存器, 指向的描述符表为全局描述符表GDT
(Gloabl Descriptor Table
)
它包含所有任务都可用的段描述符,其中包括描述操作系统所使用的代码段,数据段和堆栈段的描述符及个任务的LDT
段等;全局描述符表有且只有一个
LDTR
,是一个16位的寄存器,指向局部描述符表LDT
(Local Descriptor Table
),每个任务一个独立的LDT
。
LDTR
,是一个16位的寄存器,指向局部描述符表LDT
(Local Descriptor Table
),每个任务一个独立的LDT
。它包含每个任务私有的代码段,数据段和堆栈段的描述符,也包含一些门的描述符,如任务门和调用门的描述符等
段选择器
段选择器是16位的,但是只有高13位表示索引值。前三位表示的含义如下;
- 0,1位表示程序的当前优先级
RPL
TI
位用来表示段描述符的位置;TI = 0
表示在GDT
中,TI = 1
表示在LDT
中
一个段选择器要做如下操作步骤才能找到基址
如果TF = 0
- 从GDTR寄存器中获取GDT的基址
- 将段选择器高13位当作索引得到段描述符
- 通过段描述符获取基址、限长、优先级等各种属性
- 以基址加上偏移地址得到最后的线性地址
如果TF = 1
- 从GDTR寄存器中获取GDT的基址
- 从LDTR中获取LDT所在段的位置索引
- 以段的位置的索引在GDT中得到LDT段的位置
- 将段选择器高13位当作索引得到段描述符
- 通过段描述符获取基址、限长、优先级等各种属性
- 以基址加上偏移地址得到最后的线性地址
内存分页机制
将物理地址不连续的内存的映射连在一起,在线性地址上视为连续。
同样他解决的是内存碎片化的问题
PG = 0 禁用分页,这时所有的
指令寻址的地址就是系统中的实际物理地址
PG = 1 启用分页,所有的线性地址要经过页表的映射才得到最后的物理地址
禁用分页读取数据步骤
- 线性地址就是物理地址,处理器直接从物理内存存取数据。
启用分页读取数据的步骤
- 更具页目录和页表指定的映射关系把地址映射到物理内存的真正位置
- CPU以映射后的物理地址在物理内存中存取数据
不管用那种机制,所有寻址指令使用的都是线性地址。