3

背景信息:我在 QEMU 下运行 Xv6,并使用 GDB 作为调试器。我正在逐步浏览引导加载程序以查看它的功能。Xv6 旨在在加载内核之前切换为 32 位代码。

在汇编文件bootasm.S中,跳转到 32 位。进行转换的指令如下:

# Complete transition to 32-bit protected mode by using long jmp
# to reload %cs and %eip.  The segment descriptors are set up with no
# translation, so that the mapping is still the identity mapping.
ljmp    $(SEG_KCODE<<3), $start32

跳转之前的分段地址寄存器(由CSEIP连接的寄存器组成)的值,可以从GDB's info reg命令中读取,是CS=0x0:EIP=7c2c.

跳转之后,分段地址就是 now CS=0x8:EIP=0x7c31,这里0x7c31是 32 位代码的开始地址(包含在 bootasm.S 下start32)。.

我知道分段地址通过乘以CS16 并EIP作为偏移量添加到物理地址中。例如,当 时CS = 0x0,物理地址为(0x10 * 0xf000) + 0x7c2c = 0xf0000 + 0x7c2c = 0xf7c2c

我的问题是关于CS寄存器的内在价值。现在如何CS0x0等于0x8运行 32 位代码?如果我理解正确,基于如何0x0 * 16 = 0xf0000,那么0x8 * 16 = 0xf0080,对吗?但是这个分段地址如何等同于 32 位呢?还是我只是误解了CS寄存器的值代表什么?

编辑:感谢回复,我意识到LGDT在跳转之前执行的指令是相关的。这是跳转前的指令及其后续指令,可在以下位置找到bootasm.S

# Switch from real to protected mode.  Use a bootstrap GDT that makes
# virtual addresses map directly to physical addresses so that the
# effective memory map doesn't change during the transition.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE, %eax
movl    %eax, %cr0
4

0 回答 0