问题描述
在bootasm.S
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R,0x0,0xffffffff) # code seg
SEG_ASM(STA_W,0xffffffff) # data seg
gdtdesc:
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
.long gdt # address gdt
这是用在
lgdt gdtdesc
gdtdesc的第一个字不应该是gdt的字节大小吗?在这种情况下,它是 3*8=24
,它等于 gdtdesc - gdt
。
为什么gdtdesc - gdt - 1
在这里?
解决方法
根据手册,lgdt
想要以字节为单位的 GDT 大小,但也将其描述为“限制”。该措辞在最后一个字节的大小与地址之间存在歧义。 (这是一种允许更高限制而不包含 16 位限制的方法。)
但是 https://wiki.osdev.org/GDT_Tutorial 中的示例使用 sizeof(gdt),因此这可能是 xv6 或 osdev 教程中的错误。
https://wiki.osdev.org/Global_Descriptor_Table 同意 xv6,说“limit”是 size-1,与 GDT 教程不同。这是有道理的:
size
是表的大小减去 1。 这是因为 size 的最大值是 65535,而 GDT 最多可以是 65536 字节(最大8192 个条目)。此外,任何 GDT 的大小都不能为 0。
如果要确认详细信息,请查看 Intel 或 AMD 的手册;他们希望在系统开发细节的某处澄清这一点,与 lgdt
的指令集参考条目分开。
或者你希望他们会。但不幸的是,英特尔表示:
第 2.4.1 节全局描述符表寄存器 (GDTR)
“表限制指定表中的字节数”。
这可能只是意味着编写它的人如此陷入限制 = 最后一个字节的偏移量 = 大小的想法,以至于他们甚至没有意识到这一点还不清楚。段限制本身(在 GDT 条目中)也以这种方式工作,使用 0xFFFFF
(粒度=页面)将限制指定为 4GiB 地址空间的最顶部,即无限制。