问题描述
在为 x86 编写的典型简单引导加载程序中,我们有以下代码来加载 GDT 并执行远跳转(注意,在执行以下代码之前,CS 为 0x0):
lgdt gdtdescmovl %cr0, %eax或 $1, %eaxmovl %eax, %cr0# 跳转到下一条指令,但在 32 位代码段.# 将处理器切换到 32 位模式.ljmp $0x8, $protcseg.code32 # 汇编为 32 位模式保护段:
然而,就在 lgdt
之后,CS 为空,指向 GDT 中的空描述符.所以:
1.lgdt
加载GDT后,CPU到底是怎么取到正确指令的?
2.远跳转到的代码段的DPL通常为0,CPU在进行远跳转时是否进行权限检查?
在远跳转从 GDT 条目加载内部 CS 基础/限制/内容之前,您根本没有使用任何 GDT 条目.它甚至不是真的保护模式.
与启用分页不同(在写入 CR0 后,下一条指令的取指令将 CS:EIP 在下一条指令中视为虚拟),直到写入段寄存器导致 CPU 实际从GDT.
LGDT 不会更改 CS 基址,并且您仍然处于最大权限级别,操作数大小 = 地址大小 = 16,因此 ljmp
指令的代码提取只是发生.(假设此代码段的执行以实模式或虚模式开始.)处于保护模式会影响将 CS 更新为 8
的含义,但不影响执行该操作的指令的获取和运行.>
我不知道它是否算作 CPL=0 或是否是特殊情况的正式细节,或者如果您的第一次远跳是到呼叫门会发生什么.如果您想要更多,请查看 https://wiki.osdev.org/GDT_Tutorial和/或 Intel 或 AMD 的手册,或者其他人会回答这个问题.
In a typical simple bootloader writing for x86, we have the following code to load the GDT and perform a far jump (note that CS is 0x0 before executing the following code):
lgdt gdtdesc
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp $0x8, $protcseg
.code32 # Assemble for 32-bit mode
protcseg:
However, just after lgdt
CS is null, pointing to a null descriptor in GDT. So :
1.How on earth can the CPU fetch the correct instruction just after GDT is loaded by lgdt
?
2.DPL of the code segment to far-jump to is usually 0, does the CPU perform privilege check when doing the far jump?
Until the far jump loads the internal CS base/limit/stuff from a GDT entry, you're not using any GDT entry at all. It's not really even protected mode.
Unlike enabling paging (where instruction fetch for the next instruction treats CS:EIP as virtual in the next instruction after writing CR0), segment stuff doesn't happen until after a writing a segment register causes the CPU to actually read from the GDT.
The CS base address isn't changed by LGDT, and you're still at maximum privilege level with operand-size = address-size = 16, so code-fetch of the ljmp
instruction just happens. (Assuming execution of this snippet started in real or unreal mode.) Being in protected mode affects the meaning of updating CS to 8
, but doesn't affect fetching and running the instruction that does that.
I don't know the formal details of whether it counts as CPL=0 or if it's a special case, or what would happen if your first far jump was to a call gate. If you want more than that, have a look at https://wiki.osdev.org/GDT_Tutorial and/or Intel or AMD's manuals, or maybe someone else will answer this question.
这篇关于x86 处理器如何在引导加载程序加载 GDT 后立即获取指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!