GDTR、LDTR、GDT、LDT的理解’

本文介绍了LDTR(局部描述符表寄存器)和GDT(全局描述符表)的概念,重点阐述了LDTR如何在保护模式下通过段选择子在GDT中找到LDT的位置,以及GDT的使用和GDTR寄存器的作用。内容涉及到Intel 80386架构中的段寄存器、地址转换和段描述符。

           网上关于GDT与LDT的内容很多,这里只是在别人的基础上加入了自己理解的内容,首先贴一段LDTR的百度百科说明:

          LDTR(Local Descriptor Table Register)即局部描述符表寄存器,为自intel 80386起引入的寄存器。其中存放内容由两部分构成,第一部分为16位的LDT(局部描述符表)段的段选择子;第二部分为LDT段的段描述符的内容,intel 80386起引入的寄存器。(保护模式下为32位,IA_32e模式下为64位)、段限、段的性质描述。当进程切换时,LDTR中自动载入新进程描述符的选择子(其实是该描述符在GDT中的索引),地址转换时,若相应段寄存器(DS,CS,SS,ES)TI=1时,会根据LDTR中的描述符选择子(索引)在GDT中找到LDT的描述符,该描述符中记录着LDT的基址,然后再根据相应段寄存器(保护模式下应该叫段选择子)的高13位(该段描述符在LDT中的索引)在LDT中找到该段的描述符,而段基址就在该描述符中,段基址+偏移地址=线性地址,然后在根据是否启用分页,把线性地址转换成最终的物理地址(具体转化过程不再本词条讨论范围,可参考其它资料),当cpu或者重启时,段选择子与段基址默认值为0,段限为0FFFFH(64KB)。

          这里面有一点对理解GDT和LDT至关重要:LDTR中装在的并不是LDT表的描述符,而是一个选择子,也就是一个索引值,该索引值指明了当前LDT表的描述符在GDT表中的位置。如果段寄存器的TI=1,则根据GDTR找到GDT表,然后根据LDTR在GDT中搜索到LDT的描述符,即找到LDT表的位置,然后根据段寄存器中存储的段选择子找到需要的段基址,注意LDT表中只有三个条项,LDT[0]为空LDT[1]为代码段基址,LDT[2]为数据段基址。
         全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。


关于GDTR寄存器,段选择子,描述符具体内容请参考:

http://www.techbulo.com/708.html

### GDT(全局描述符表) GDT 是保护模式下内存段(数据段、代码段等)的登记表,是线性地址空间的一个数据结构,每个系统必须定义一个 GDT,用于系统中的所有任务程序。GDT 本身不是一个段,其线性基地址长度必须加载进 GDTR 之中,且基地址最好进行 8 字节对齐,因为每个描述符长度是 8 字节 [^2]。 ### LDT(局部描述符表) LDT 是任务私有的结构,一个任务对应一个 LDT,用于实现保护模式下通过虚拟地址进行内存隔离,防止一个进程访问另一个进程的代码或数据段。LDT 同样存储在内存中的一段区域中,需要在 GDT 中注册,拥有自己的描述符来描述某任务的 LDT 的起始地址及偏移量大小,以便通过段选择子准确访问。不过,由于每加入一个任务都要在 GDT 中添加新的 LDT 描述表,且任务切换时要重新加载 LDTR,操作麻烦,现在很少使用 LDT 作为多任务的切换方式了。在 Linux 中,2.4 之前使用 LDT 辅助进程任务切换,2.4 之后所有任务共享一个 LDT,这个共享 LDT 条目放在 GDT 中,默认有 3 个条目:LDT[0] 为空;LDT[1] 为用户代码段;LDT[2] 为用户数据/堆栈段描述符,Linux 所生成的 LDT 的大小是 24 个字节 [^1][^3]。 ### TSS(任务状态段) TSS 用于进程任务切换。在 Linux 2.4 之前使用 TSS 进行进程任务切换,但 TSS LDT 中的每一个条目都应该保存在 GDT 中,这限制了系统中的任务总数 [^1]。 ### 代码示例 以下是一个简单的伪代码示例,用于说明加载 GDT LDT 的概念: ```asm ; 定义 GDTgdt_start: ; 空描述符 dd 0x0 dd 0x0 ; 代码段描述符 dw 0xFFFF ; 段界限低 16 位 dw 0x0 ; 段基地址低 16 位 db 0x0 ; 段基地址中 8 位 db 10011010b ; 访问权限 db 11001111b ; 其他标志段界限高 4 位 db 0x0 ; 段基地址高 8 位 ; 数据段描述符 dw 0xFFFF ; 段界限低 16 位 dw 0x0 ; 段基地址低 16 位 db 0x0 ; 段基地址中 8 位 db 10010010b ; 访问权限 db 11001111b ; 其他标志段界限高 4 位 db 0x0 ; 段基地址高 8 位 gdt_end: ; GDT 描述符 gdt_descriptor: dw gdt_end - gdt_start - 1 ; GDT 长度 dd gdt_start ; GDT 基地址 ; 加载 GDT lgdt [gdt_descriptor] ; 假设 LDT 描述符已经在 GDT 中 ; 加载 LDT mov ax, 0x10 ; 假设 LDT 选择子为 0x10 lldt ax ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值