GDT/LDT/GDTR/LDTR

实模式与保护模式

 实模式是所有 x86 兼容 CPU 下的一种操作模式。特点是 20 bit 分段内存地址空间,对所有可寻址内存、I/O地址和外设硬件的无限制直接软件访问。实模式不支持内存保护、多任务处理与代码权限级别。

 最早期的 8086 CPU 只有实模式,数据总线为 16 位,地址总线为 20 位,所有寄存器都是 16 位。从 80286 开始就有了保护模式,允许硬件级内存保护。从 80386 开始 CPU 数据总线和地址总线均为 32 位,且寄存器都是 32 位。

 逻辑地址是逻辑上的地址,实模式下由段基地址+段内偏移组成,保护模式下由段选择符+段内偏移组成。逻辑地址经分段后就成线性地址,如果不启用分页,那么此线性地址即物理地址。线性地址经分页后成为物理地址。

 8086 CPU 数据总线为 16 位,一次最多取 2^16B=64KB 数据,因此实模式下每个段为 64KB,其地址总线为 20 位,因此 8086 CPU 寻址能力是 2^20=1MB。要用 16 位的段寄存器表示 1MB 的寻址能力,因此就有了分段的概念。8086 CPU 将 1MB 存储空间分成许多逻辑段,每个段最大为 64KB,这样存储单元可用段基地址+段内偏移表达(其中段基地址是 16 位段寄存器值左移 4 位)。

保护模式和实模式的区别在于用段选择符而还是段基地址。下图为保护模式从逻辑地址到线性地址的转换:

image-20240606134202766

 上图中的段选择符、描述符表等概念解释如下所示:

  • 段选择符。段选择符为 16 位,它指向段描述符。其中 TI 指明使用全局描述符表 GDT 还是局部描述符表 LDT。RPL表示请求特权级。索引值为 13 bit,所以在保护模式下最多可表示 2^13=8192 个段描述符,加上 TI,一共可表示 8192*2=16384 个段描述符,也就是 16384 个段。由于偏移地址为 32 位(4GB),所以寻址能力为 16384*4GB=64TB。例如,远跳转指令 jmpi 0, 8。其中的 8 以段描述符的结构进行解析,得到索引=1TI=0RPL=00,所以这条语句的意思是跳转到 GDT 表(TI=0)中的第 1 个段描述符定义的段中,其段内偏移为 0。再例如,给出逻辑地址 21h:12345678h 转换为线性地址,段选择符为 0x21,解析得到:索引=4TI=0RPL=1,若此时 GDT 第 4 个描述符中描述的段基址为 11111111h,则线性地址=11111111h+12345678h=23456789h

image-20240606134753605

image-20240606144212785

  • 段描述符。段描述符表中的每一项为 64 位。段描述符里有三个基地址信息,共同组成一个 32 位地址(段基地址),此地址再加上段内偏移就是线性地址。S 位和 TYPE 字段的不同又将段分为数据段描述符、代码段描述符和系统段描述符。

image-20240606141544302

 保护模式通过段选择符指向段描述符,最终由段描述符+段内偏移定位线性地址。之后就是分页机制,其将线性地址转为物理地址。这在 ace-prepare 中有描述,就不介绍了。

GDT/LDT 相关

 一个 CPU 对应一个全局描述符表(GDT,Global Descriptor Table),GDTR 寄存器用于存放 GDT 的入口线性地址与表长(使用 LGDT 指令可以将 GDT 的入口地址放入 GDTR 寄存器)。

image-20240606145006990

 局部描述符表(LDT,Local Descriptor Table)可以有多张,可以理解为 GDT 为一级描述符表,LDT 为二级描述符表。LDT 嵌套在 GDT 中。实际 windows 中不会使用 LDTR。

 举两个例子,分别访问 GDT 与 LDT。访问 GDT(TI=0)的流程为:

Step1:从 GDTR 寄存器中获得 GDT 基址。

Step2:在 GDT 中以段选择符高 13 位位置索引值得到段描述符。

Step3:段描述符包含段的基址、限长、优先级等各种属性,这就得到了段的基址,基址加上偏移地址就得到最后的线性地址。

image-20240606154313306

 访问 LDT(TI=1) 的流程为:

Step1:从 GDTR 寄存器中获得 GDT 基址。

Step2:从 LDTR 寄存器中获取 LDT 所在段的位置索引。

Step3:根据位置索引在 GDT 中得到 LDT 段描述符,从而得到 LDT 段基址。

Step4:用段选择器高 13 位位置索引值从 LDT 段中得到段描述符。

Step5:段描述符包含段的基址、限长、优先级等各种属性,这就得到了段的基址,基址加上偏移地址就得到最后的线性地址。

image-20240606155811710

IDTR/TR 相关

  • 中断描述符表寄存器 IDTR。与 GDTR 类似,IDTR 用于存放中断描述符表 IDT 的基地址和表长。

  • 任务寄存器 TR。用于寻址一个特殊的任务状态段(TSS,Task State Segment),TSS 包含当前执行任务的重要信息,主要是 ring3 到 ring0 中使用,改变 SS、CS 段与 ESP。

参考链接

[1] https://blog.csdn.net/chungle2011/article/details/80069703

[2] https://www.cnblogs.com/shiqi17/p/12667236.html

[3] https://s0rry.cn/posts/Windows-Protection/

[4] https://www.cnblogs.com/kelamoyujuzhen/p/10555924.html

留言

© 2024 wd-z711

⬆︎TOP