GDT(全局描述符表)和LDT(局部描述符表)
每个程序都有自己的LDT,但是同一台计算机上的所有程序共享一个GDT。
LDT描述局部于每个程序的段,包括其代码、数据、堆栈等。
GDT描述系统段,包括操作系统本身。
①全局描述符表GDT(Global Descriptor Table)
在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此积存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。
GDTR中存放的是GDT在内存中的基地址和其表长界限。
GDTR结构②段选择子(Selector)由GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的。为了访问一个段,一个Pentium程序必须把这个段的选择子装入机器的6个段寄存器的某一个中。
在运行过程中,CS寄存器保存代码段的选择子,DS寄存器保存数据段的选择子。每个选择子是一个16位数。
selector选择子中的一位指出这个段是局部的还是全局的(它是在LDT中还是在GDT中),其他的13位索引是LDT或GDT的表项编号,表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符,然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)
的OFFSET就可以转换成线性地址。因此,这些表的长度被限制在最多容纳8K个段描述符。
段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。任务中的每一个段都有一个特定的级别。
每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。
例如给出逻辑地址:21h:12345678h转换为线性地址
a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;
左后的01b代表特权级RPL=1
b. OFFSET=12345678h若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h
③局部描述符表LDT(Local Descriptor Table)
局部描述符表可以有若干张,每个任务可以有一张。
我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。如图
gdt寻址
LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。
LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。
由于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是这样一个选择子。
LDTR可以在程序中随时改变,通过使用lldt指令。
如上图,如果装载的是Selector 2则LDTR指向的是表LDT2。
举个例子:如果我们想在表LDT2中选择第三个描述符所描述的段的地址12345678h。
-
首先需要装载LDTR使它指向LDT2 使用指令lldt将Select2装载到LDTR
-
通过逻辑地址
(SEL:OFFSET)
访问时SEL的index=3代表选择第三个描述符;TI=1代表选择子是在LDT选择,此时LDTR指向的是LDT2,所以是在LDT2中选择,此时的SEL值为1Ch(二进制为11 1 00b)。
OFFSET=12345678h。逻辑地址为1C:12345678h -
由SEL选择出描述符,由描述符中的基址(Base)加上OFFSET可得到线性地址,例如基址是11111111h,则线性地址=11111111h+12345678h=23456789h
-
此时若再想访问LDT1中的第三个描述符,只要使用lldt指令将选择子Selector 1装入再执行2、3两步就可以了(因为此时LDTR又指向了LDT1)
由于每个进程都有自己的一套程序段、数据段、堆栈段,有了局部描述符表则可以将每个进程的程序段、数据段、堆栈段封装在一起,只要改变LDTR就可以实现对不同进程的段进行访问。
段描述符:
P,present位,1表示所描述的段存在(有效),为0表示所描述的段无效,使用该描述符会引起异常
DPL,Descriptor privilege,描述符特权级别,说明所描述段的特权级别
DT,描述符类型位,1说明当前描述符为存储段描述符,0为系统描述符或门描述符.
TYPE:
位0:A(accessed)位,表明描述符是否已被访问;把选择子装入段寄存器时,该位被标记为1
位3:E(EXECUTABLE?)位,0说明所描述段为数据段;1为可执行段(代码段)
当为数据段时,
位1为W位,说明该数据段是否可写(0只读,1可写)
位2为ED位,说明该段的扩展方向(0向高位扩展,1向低位扩展)
当为可执行段是,
位1为R位,说明该执行段是否可读(0只执行,1可读)
位2为C位,0说明该段不是一致码段(普通代码段),1为一致码段
G为粒度位,0说明LIMIT粒度为字节,1为4K字节.
D位:
1.在可执行段中,D为1,表示使用32位地址,32/8位操作数;为0表示使用16位地址,16/8位操作数
2.在由SS寻址的段描述符(堆栈段?)中,D为1表示隐含操作(如PUSH/POP)使用ESP为堆栈指针,
为0使用SP(隐含操作:未明确定义段属性类型USE16/USE32?66H,67H?)
3.在向低扩展的存储段中,D为1,表示段的上限为4G;为0上限为64K
存储段描述符的结构表示:
分段管理可以把虚拟地址转换成线性地址,而分页管理可以进一步将线性地址转换成物理地址。
当CR0中的PG位置1时,启动分页管理功能,为0时,这禁止启动分页管理功能,并且把线性地址作物理地址使用。
虚拟地址转为线性地址:
线性地址= 段基指 + 偏移地址
32位线性地址转为物理地址:
32位分为:
页目录索引:占最高10位,指示页目录表中第几个页表描述符
页表索引:占12位到21位,也是10位。指示这页表中第几个页描述符
页描述符:线性地址的低12位为页内偏移量。