分段机制把逻辑地址转换为线性地址。
以段寄存器为基础的保护模式(Protected Mode): 原有的4个16位段寄存器(CS、DS、SS、ES)
新增的2个16位段寄存器(FS、GS)
增设了2个寄存器(GDTR、LDTR)
其中,GDTR(Global Descriptor Table Register,全局段描述符表寄存器)
LDTR(Local Descriptor Table Register,局部段描述符表寄存器)
用来指向存储在内存区域中的一个段描述结构数组,也就是段描述符表。
在此基础上,上述6个16位的段寄存器中存放的就不再是某个段的基地址,而是某个段的选择符(Segment Selector)。在这个选择符中,高13位用作访问段描述符表的下标(index)。
段选择符
15 3 2 0
| index | TI | RP |
从8192(2^13)个全局或局部 _| | |____表示特权级别:00=最高级,
描述表项中选择一个描述符 | 11=最低级
TI=0时,使用GDTR
TI=1时,使用LDTR
因此,具体的段描述符表项的起始地址 = 段选择符的低3位屏蔽后,与GDTR或LDTR中给定的基地址相加来决定。
在段描述符表中,每个段描述符表项的大小都是8 Byte,含有段的基地址,段大小,段的保护等级,段是系统段还是用户段,段的类型特征和它的存取权限等信息。另外,Protected Mode,顾名思义,又为段模式提供了保护机制,也就是说一个段的描述符需要规定对自身的访问权限(Access),因此,在Protected Mode下,对一个段的描述包括3个方面的因素:
Base Address
Limit
Access
上述三者加在一起被放在一个64-bit长的数据结构中,即段描述符。
在这种情况下,如果我们直接通过一个64-bit段描述符来引用一个段的时候,就必须使用一个64-bit长的段寄存器装入这个段描述符,但Intel为了保持向后兼容,将段寄存器仍然规定为16-bit。
因此,将这些长度为64-bit的段描述符放入一个数组中,而将段寄存器中的值作为下标索引来简介引用(事实上,是将段寄存器中的高13-bit的内容作为索引)。这个全局的数组就是GDT(事实上,GDT中存放的不仅仅是段描述符)。
GDT可以被放在内存的任何位置,那么当程序员通过段寄存器来引用一个段描述符时,CPU必须知道GDT的入口,也就是基地址放在哪里,所以Intel的设计者们提供了一个寄存器GDTR用来存放GDT的入口地址。
程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。
GDT仅有一个,而且是全局可见的,对任何一个任务而言都是这样。
除了GDT之外,IA-32还允许程序员构建和GDT类似的数据结构,LDT。LDT在系统中可以存在多个,并且只对引用它们的任务可见,每个任务最多可以拥有一个LDT。LDT自身作为一个段存在,它们的段描述符被放在GDT中。
IA-32为LDT的入口地址也提供了一个寄存器LDTR,因为在任何时刻只能有一个任务在运行,所以LDT寄存器全局也只需要有一个。
如果一个任务拥有自身的LDT,那么当它需要引用自身的LDT时,它需要通过LLDT将其LDT的段描述符装入此寄存器。
LLDT指令与LGDT指令不同的是:
LGDT指令的操作数是一个32-bit的内存地址,这个内存地址处存放的是一个32-bit GDT的入口地址,以及16-bit的GDT Limit;
而LLDT指令的操作数是一个16-bit的选择子,这个选择子的主要内容是:被装入的LDT的段描述符在GDT中的索引值。
逻辑地址的转换过程:
1.先检查段选择符的TI字段,以决定段描述符保存在哪一个描述符表中,分别从GDTR或LDTR寄存器中得到GDT或LDT的线性基地址;
2.从段选择符的index字段计算段描述符的地址,即index字段的值乘以8,并将这个结果与GDTR或LDTR寄存器中的内容相加;
3.把逻辑地址的偏移量与段描述符Base字段的值相加就得到了线性地址。
阅读(889) | 评论(0) | 转发(0) |