我正在阅读 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

希望这会有所帮助!另请参阅以下引用资料以清除 GDTLGDT 的概念

关于c - 全局描述符表的物理地址?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21128311/

10-11 19:44