我的代码中有以下情况:
.code16
// NOTE: current CS:IP address is 0x8000:0000
lgdt kernel_gdt_descriptor
// Enable PE bit in cr0 register
mov %cr0, %eax
or %eax, $0x1
mov %eax, %cr0
ljmp 0x8, _pmode_entry
_pmode_entry:
jmp _pmode_entry
我知道执行到CS = 0x8的长跳转将选择第一个段描述符条目,在我的情况下跨越所有可寻址的32位存储器,并且执行跳转到该位置(0x00000000 + _pmode_entry)。
这当然不是_pmode_entry
的实际位置,而只是偏移。 _pmode_entry的实际32位位置是(0x8000 * 16 + 0x0),但我不知道如何跳转到此位置,因为CS寄存器现在用于选择描述符,并且我的以下尝试无法编译。
根据我在Intel developers manual,第616页中找到的摘录:
在实地址或虚8086模式下执行远跳时, 处理器跳转到代码段和指定的偏移量 目标操作数。这里目标操作数指定绝对远 用指针直接寻址(ptr16:16或 ptr16:32 )或 间接存储位置(m16:16或m16:32)
因此,我理解以下说明是合法的:
ljump $0x8, $0x0080000
在我看来,这会选择第一个段描述符,然后跳转到该段内的存储单元0x00800000。但是,GNU AS失败了
Error: 16 bit jump out of range
。