Global Descriptor Table

来自osdev
Zhang3讨论 | 贡献2021年12月21日 (二) 07:20的版本 (创建页面,内容为““全局描述符表”(“GDT”)是特定于 IA-32]和[[X86-64 | X86-64体系结构的二进制数据结构。它包含告诉CPU关于内存分段的条目。 类似的中断描述符表包含任务中断描述符。 建议阅读GDT教程。 == GDTR == “GDT”由“GDTR”寄存器中的值指向。 这是使用“LGDT”汇编指令加载的,该指令的参数是指向“GDT描述符”…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

“全局描述符表”(“GDT”)是特定于[[IA32_体系结构| IA-32]和 X86-64体系结构的二进制数据结构。它包含告诉CPU关于内存分段的条目。 类似的中断描述符表包含任务中断描述符。

建议阅读GDT教程

GDTR

“GDT”由“GDTR”寄存器中的值指向。 这是使用“LGDT”汇编指令加载的,该指令的参数是指向“GDT描述符”结构的指针:

GDT Descriptor (GDTR)
79 (64-bit mode)
48 (32-bit mode)   16
15   0
Offset
63 (64-bit mode)
31 (32-bit mode)   0
Size

15   0
  • Size: 表的大小(以字节为单位)减去1。之所以发生此减法,是因为“Size”的最大值为65535,而“GDT”的长度最多为65536字节(8192个条目)。此外,任何“GDT”的大小都不能为0字节。
  • Offset: “GDT”的线性地址(不是物理地址,分页适用)。

请注意,“LGDT”加载的数据量在32位和64位模式下有所不同,偏移量在32位模式下为4字节长,在64位模式下为8字节长。

有关更多信息,请参见“第2.4节”。1:《英特尔软件开发人员手册》第3-A卷的“全局描述符表寄存器(GDTR)”和“图2-6:内存管理寄存器”。

表格

“GDT”中的条目长度为8字节,形成如下表格:

Global Descriptor Table
Address Content
GDTR Offset + 0 Null
GDTR Offset + 8 Entry 1
GDTR Offset + 16 Entry 2
GDTR Offset + 24 Entry 3
... ...

“'GDT'”(条目0)中的第一个条目应始终为空,并应使用后续条目。

“段选择器”可访问表中的条目,它们通过汇编指令或硬件功能(如“Interrupts”加载到“Segmentation”寄存器中。

段描述符

表中的每个条目都有一个复杂的结构:

Segment Descriptor
63   56 55   52 51   48 47   40 39   32
Base
31   24
Flags
3   0
Limit
19   16
Access Byte
7   0
Base
23   16
31   16 15   0
Base
15   0
Limit
15   0
  • Base: 一个32位的值,包含段开始的线性地址。
  • Limit: 一个20位的值,以1字节单位或4KB页面表示最大可寻址单元。 因此,如果选择页面粒度并将“限制”值设置为0xFFFFF,则该段将在32位模式下跨越整个4 GiB地址空间。

在64位模式下,忽略“Base”和“Limit”值,每个描述符覆盖整个线性地址空间,而不管它们设置为什么。

有关更多信息,请参见“第3.4节”。《英特尔软件开发人员手册》第3-A卷第5部分:段描述符“”和“图3-8:段描述符”。

Access Byte
7 6 5 4 3 2 1 0
Pr Privl S Ex DC RW Ac
  • Pr: 当前位。 允许条目引用有效段。 Must be set (1) for any valid segment.
  • Privl: 描述符特权级别字段。 包含段的 CPU特权级别0 = highest privilege (kernel), 3 = lowest privilege (user applications).
  • S: 描述符类型位。 If clear ('0) the descriptor defines a system segment (eg. a Task State Segment). 如果设置(1),则定义代码或数据段。
  • Ex: Executable bit. If clear (0) the descriptor defines a data segment. If set (1) it defines a code segment which can be executed from.
  • DC: Direction bit/Conforming bit.
 ** For data selectors: Direction bit. If clear (0) the segment grows up. If set (1) the segment grows down, ie. the Offset has to be greater than the Limit.
 ** For code selectors: Conforming bit.
 *** If clear (0) code in this segment can only be executed from the ring set in Privl.
 *** If set (1) code in this segment can be executed from an equal or lower privilege level. For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. The Privl field represent the highest privilege level that is allowed to execute the segment. For example, code in ring 0 cannot far-jump to a conforming code segment where Privl is 2, while code in ring 2 and 3 can.  请注意,特权级别保持不变,即。 a far-jump from ring 3 to a segment with a Privl of 2 remains in ring 3 after the jump.
  • RW: Readable bit/Writable bit.
 ** For code segments: Readable bit. If clear (0), read access for this segment is not allowed. If set (1) read access is allowed. 决不允许对代码段进行写访问。
 ** 对于数据段:可写位。 If clear (0), write access for this segment is not allowed. If set (1) write access is allowed. Read access is always allowed for data segments.
  • Ac: Accessed bit. Best left clear (0), the CPU will set it when the segment is accessed.
Flags
3 2 1 0
Gr Sz L Reserved
  • Gr: Granularity flag, indicates the size the Limit value is scaled by. If clear (0), the Limit is in 1 Byte blocks (byte granularity). If set (1), the Limit is in 4 KiB blocks (page granularity).
  • Sz: Size flag. If clear (0), the descriptor defines a 16-bit protected mode segment. If set (1) it defines a 32-bit protected mode segment. A GDT can have both 16-bit and 32-bit selectors at once.
  • L: Long-mode code flag. If set (1), the descriptor defines a 64-bit code segment. When set, Sz should always be clear. For any other type of segment (other code types or any data segment), it should be clear (0).

另见

文章

外部参照

 de:Global Descriptor Table