切换到保护模式后CPU如何寻址下一条指令?MIT6.828实验疑问
MIT6.828实验1:实模式转保护模式的疑问解答
问题描述
我正在完成MIT6.828的实验1,对切换到保护模式的代码存在疑问。相关汇编代码如下:
# Switch from real to protected mode, using a bootstrap GDT # and segment translation that makes virtual addresses # identical to their physical addresses, so that the # effective memory map does not change during the switch. lgdt gdtdesc movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0 # Jump to next instruction, but in 32-bit code segment. # Switches processor into 32-bit mode. ljmp $PROT_MODE_CSEG, $protcseg
执行movl %eax, %cr0时,IP寄存器存储的是ljmp $PROT_MODE_CSEG, $protcseg指令的物理地址。但执行该指令后,CPU进入保护模式,CS和IP寄存器的值却未改变。此时CPU需通过CS和IP寄存器取值来获取下一条指令,但CS寄存器并非有效段选择子,无法通过它得到正确的物理地址,这一过程是如何实现的?我查阅了英特尔架构手册,但未找到答案。
解答
核心逻辑是:CR0的PE位置1后,CPU不会立刻完全进入保护模式,而是要等到执行下一条控制转移指令(此处为ljmp)才完成彻底切换,中间的指令读取依赖预取机制,不会触发段翻译问题。
- 指令预取的作用:当
movl %eax, %cr0执行时,CPU已经把紧跟其后的ljmp指令预取到了指令队列中。所以PE位被置1后,CPU不需要重新通过段机制去内存读取ljmp指令,直接执行队列里的预取指令即可。 - 远跳转完成模式切换:这条
ljmp是远跳转指令,它会直接将CS寄存器加载为合法的段选择子PROT_MODE_CSEG,同时把EIP设置为32位的protcseg地址。执行这条指令时,CPU会从GDT中加载对应段的描述符到CS的描述符缓存器,从此彻底启用32位保护模式的段翻译规则。 - 过渡状态的段机制:在PE位置1到远跳转执行完成的间隙,CPU仍沿用实模式的段地址计算方式(段值×16+偏移),但因为
ljmp指令已经被预取,不需要访问内存取指,所以即使CS此时不是保护模式下的有效段选择子,也不会出现地址错误。
内容的提问来源于stack exchange,提问作者QZero
相关产品推荐
相关产品推荐

