我正在阅读 mit os 内核代码的反汇编代码。我认为内核代码应该遵循相同的规则。
我看到内核中加载全局描述符表的指令如下:
lgdtl 0x10f018
我知道 lgdt 以 GDT(16 位)的长度和 GDT(32 位)的地址作为操作数。但是,我无法从命令中得知 GDT 的地址是什么。
我检查了从 0x10f0 和 0xf018 开始的 8 字内存内容。从这两个地址开始的所有 8 个字都为零。
我的问题是:lgdtl 0x10f018
中的 GDT 地址是什么?你是怎么告诉它的?机器是intel 32bit。
是否有任何寄存器保存 GDT 的地址?我正在使用 bochs 来运行操作系统,所以如果我知道寄存器,也许我可以打印出寄存器的内容。
非常感谢您的帮助!
[修改]
我环顾四周,发现 lgdtl ADDR 意味着将 ADDR 处的内容加载到 GDTR。所以ADDR 的内容就是GDT 的限制和地址。我打印出 0x10f018 处的内存内容:
<bochs:24> x /8wx 0x10f018
[bochs]:
0x0010f018 <bogus+ 0>: 0xf0000017 0x00000010 0x32311b00 0x36353433
0x0010f028 <bogus+ 16>: 0x30393837 0x09083d2d 0x72657771 0x69757974
下面是 GDT 的设置
###################################################################
# setup the GDT
###################################################################
.p2align 2 # force 4 byte alignment
mygdt:
SEG_NULL # null seg
SEG(STA_X|STA_R, -KERNBASE, 0xffffffff) # code seg
SEG(STA_W, -KERNBASE, 0xffffffff) # data seg
mygdtdesc:
.word 0x17 # sizeof(mygdt) - 1
.long RELOC(mygdt) # address mygdt
我的问题是:我该如何解释
0x0010f018 <bogus+ 0>: 0xf0000017 0x00000010 0x32311b00
获取GDT的地址?
顺便说一句,0x00f01000 处的内容如下。我认为它可能是 GDT,但不是。 :(有人可以帮忙吗?
<bochs:31> x /16wx 0x00f01000
[bochs]:
0x00f01000 <bogus+ 0>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00f01010 <bogus+ 16>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00f01020 <bogus+ 32>: 0x00000000 0x00000000 0x00000000 0x00000000
0x00f01030 <bogus+ 48>: 0x00000000 0x00000000 0x00000000 0x00000000
解决了:
<bochs:29> x /6bx 0x10f018
[bochs]:
0x0010f018 <bogus+ 0>: 0x17 0x00 0x00 0xf0 0x10 0x00
基于little edian,寄存器有0010f000 0017
所以GDT的地址是0010f000,长度是0017;
通过查看 0010f000 处的内容可以确认这一点:
<bochs:32> x /8wx 0x0010f000
[bochs]:
0x0010f000 <bogus+ 0>: 0x00000000 0x00000000 0x0000ffff 0x10cf9a00
0x0010f010 <bogus+ 16>: 0x0000ffff 0x10cf9300 0xf0000017 0x00000010
另外,初始esp指向0x0010f000,这是GDT的起始地址。当第一个函数被调用时,堆栈从高地址增加到低地址。
内存映射如下(左为低地址):
---程序栈---|GDT
最佳答案
GDT 基本上是一个包含各种 GDT 条目的结构。 lgdtl
是将全局描述符表加载到 gdt 寄存器的指令。因此,从您的问题中回答: 0x10f018 是 GDT 基址。如果您查看代码,您会发现 GDT 被定义为结构,而 0x10f018 是该结构的地址(根据您的反汇编),在 GDT 结构中最多可以有 8192 个条目。
所以,是的 GDT 寄存器保存了 GDT 结构的基地址。 lgdt
用于设置 gdt,其格式如下: lgdt maddr
。而且,在设置 GDT 之前,您打印出寄存器内容的计划将不起作用,因为设置 GDT 的唯一方法是使用 lgdt
。
希望这会有所帮助!另请参阅以下引用资料以清除 GDT 和 LGDT 的概念
关于c - 全局描述符表的物理地址?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21128311/