GDTR、LDTR、IDTR 和 TR 寄存器的大小是多少?

What are the sizes of GDTR, LDTR, IDTR and TR registers?

我在网上查了很多,每次都只能找到GDT、LDT和IDT的大小。

这里我问的不是table的大小,而是寄存器

的大小

我知道GDTR是一个64位的寄存器,但对其他的一无所知

IDTR 和 GDTR 似乎各为 10 个字节。

IDTR 也可以指向虚拟地址 space 中的任何地方,所以显然它的基数也必须是 64 位的。 lidtlgdt 采用相同的限制/基本结构格式,the pseudocode 表明在 64 位模式下它们是这样的:

                    GDTR(Limit) ← SRC[0:15];
                    GDTR(Base) ← SRC[16:79];

应将限制(最大字节偏移量)视为 GDTR / IDTR 的一部分。 documentation for sidt 也表示“store IDTR”,它存储的是具有 limit + base 的相同 2 + 8 字节结构。 (GDTR 在内部使用限制来检查段选择器,然后再在 GDT 中查找它们,因此如果超过限制,您使用 lgdt 的地址的 64k 以内的内存可用于其他用途。)

似乎 lidt / lgdt 没有检查 GDT/IDT 基址是否为规范地址。文档说他们 #GP(0) 如果内存地址是非规范形式。 但我认为这是在谈论达到 10 字节内存操作的寻址模式运行d,不是基址。

(如果无法获得 non-canonical address into the GDTR or IDTR, the CPU could internally store only the significant (or 57 with PML5),将大小降低到 6 + 2 = 8 字节。并将符号扩展回 64 位作为 sidt / sgdt 的一部分。但可能 可以通过 GDTR 往返任意 64 位值,只需确保 CPU 在你放置之前不需要将 GDT 用于任何事情在一个有效的地址!)


LDTR 包含段选择器和整个描述符

lldt 的文档表明如果没有错误:

    LDTR(SegmentSelector) ← SRC;
    LDTR(SegmentDescriptor) ← GDTSegmentDescriptor;

表示内部LDTR保持16位段选择符(实际ope运行d到ldtr,例如ldtr ax),以及加载选择的GDT进入并保持它。 GDT 条目是 8 个字节,但它可以将该条目解码为某种内部格式。 (可能不包括类型字段,它已经被检查并要求类型为 == LDT)

这意味着像DS或SS这样的段寄存器,如果你在运行lldt之后改变了GDT的内容,你base/limit当时选择的条目运行 lldt 将继续申请。

TR 看起来与 LDTR 相似

同样,文档显示:

TaskRegister(SegmentSelector) ← SRC;
TaskRegister(SegmentDescriptor) ← TSSSegmentDescriptor;

与 LDTR 一样,您只能检索段选择器,而不能检索它存储的实际描述符。 str r/m16 and sldt r/m16 只写一个 16 位目标 ope运行d.

但是实际的内部寄存器需要保存整个段描述符,而不是用选择器重新索引当前的 GDT。

您可以随时查看 CPU 制造商所说的,英特尔® 64 和 IA-32 架构软件开发人员手册第 3 卷第 2.4 章,排序:

GDT 和 IDT:

  • 基地址 32 位或 64 位(分别在保护模式和长模式下)
  • 限制:16 位
  • 总大小:48 或 80 位(4+2=6 字节或 8+2=10 字节)
LDT 和 TR:16 位,与所有其他段寄存器一样。

你也可以看看wiki.osdev.org,这是一个关于操作系统开发的wiki。其中,它有 GDT, IDT and LDT 个页面。