我在网上查了很多,每次都只能找到GDT、LDT和IDT的尺寸。
这里我不是在问表的大小,而是在问寄存器的大小
我知道 GDTR 是一个 64 位寄存器,但对其他寄存器一无所知。
我在网上查了很多,每次都只能找到GDT、LDT和IDT的尺寸。
这里我不是在问表的大小,而是在问寄存器的大小
我知道 GDTR 是一个 64 位寄存器,但对其他寄存器一无所知。
IDTR 还可以指向虚拟地址空间中的任何位置,因此显然它的基址也必须是 64 位的。 lidt
并lgdt
采用相同的限制/基本结构格式,伪代码显示在 64 位模式下它们会:
GDTR(Limit) ← SRC[0:15];
GDTR(Base) ← SRC[16:79];
限制(最大字节偏移)应被视为 GDTR / IDTR 的一部分。的文档sidt
还说“存储 IDTR”,它存储的是相同的 2 + 8 字节结构,具有限制 + 基数。(GDTR 在内部使用限制来检查段选择器,然后在 GDT 中查找它们,因此lgdt
如果超过限制,您使用的地址的 64k 内的内存可以用于其他用途。)
似乎lidt
/lgdt
不检查 GDT/IDT 基址是否为规范地址。文档说他们#GP(0)
如果内存地址是非规范形式。但我认为这是关于达到 10 字节内存操作数的寻址模式,而不是基地址。
(如果无法在 GDTR 或 IDTR中获取非规范地址,CPU 可以在内部仅存储有效的48 位(或PML5的 57 位),从而将大小降低到 6 + 2 = 8 字节。并且将符号扩展回 64 位作为sidt
/的一部分sgdt
。但可能可以通过 GDTR 往返任意 64 位值,只需确保 CPU 在放置之前不需要使用 GDT在一个有效的地址!)
的文档lldt
表明如果没有错误:
LDTR(SegmentSelector) ← SRC;
LDTR(SegmentDescriptor) ← GDTSegmentDescriptor;
这表明内部 LDTR 保留 16 位段选择器(实际操作数ldtr
,例如ldtr ax
),以及加载选定的 GDT 条目并保留它。GDT 条目是 8 个字节,但它可以将该条目解码为某种内部格式。(可能不包括 type 字段,该字段已被检查并要求为 type == LDT)
这意味着与 DS 或 SS 等段寄存器一样,如果您在运行后更改 GDT 内容,则lldt
在您运行时所选条目的基数/限制lldt
将继续适用。
同样,文档显示:
TaskRegister(SegmentSelector) ← SRC;
TaskRegister(SegmentDescriptor) ← TSSSegmentDescriptor;
与 LDTR 一样,您只能检索段选择器,而不是它存储的实际描述符。str r/m16
并且sldt r/m16
只写一个 16 位的目标操作数。
但是实际的内部寄存器需要保存整个段描述符,而不是使用选择器重新索引当前 GDT。