设置Unreal Mode时是否需要配置CS寄存器?
关于Unreal Mode切换示例中CS寄存器与远跳转的疑问
OSDev提供的Unreal Mode切换示例代码如下:
ORG 0x7c00 ; add to offsets start: xor ax, ax ; make it zero mov ds, ax ; DS=0 mov ss, ax ; stack starts at seg 0 mov sp, 0x9c00 ; 2000h past code start, ; making the stack 7.5k in size cli ; no interrupts push ds ; save real mode lgdt [gdtinfo] ; load gdt register mov eax, cr0 ; switch to pmode by or al,1 ; set pmode bit mov cr0, eax jmp 0x8:pmode pmode: mov bx, 0x10 ; select descriptor 2 mov ds, bx ; 10h = 10000b and al,0xFE ; back to realmode mov cr0, eax ; by toggling bit again jmp 0x0:unreal unreal: pop ds ; get back old segment sti mov bx, 0x0f01 ; attrib/char of smiley mov eax, 0x0b8000 ; note 32 bit offset mov word [ds:eax], bx jmp $ ; loop forever gdtinfo: dw gdt_end - gdt - 1 ;last byte in table dd gdt ;start of table gdt: dd 0,0 ; entry 0 is always unused codedesc: db 0xff, 0xff, 0, 0, 0, 10011010b, 00000000b, 0 flatdesc: db 0xff, 0xff, 0, 0, 0, 10010010b, 11001111b, 0 gdt_end: times 510-($-$$) db 0 ; fill sector w/ 0's dw 0xAA55 ; Required by some BIOSes
针对这段代码,有以下几个疑问及解答:
疑问1:为何要操作CS?我们仅需扩大数据段限制,只需设置DS即可
操作CS是因为早期x86 CPU的设计要求:当把CR0的PE位置1进入保护模式后,必须立即执行一次远跳转来刷新指令预取队列。此时CPU的指令预取队列里还残留着实模式下的指令解码状态,远跳转能强制清空队列,让CPU完全切换到保护模式的指令解码逻辑。如果跳过这一步,后续指令可能被错误解码,直接导致系统崩溃。
疑问2:在mov cr0, eax之后(或执行近跳转刷新预取队列后),直接用mov给DS加载GDT条目是否可行?
不行。刚设置CR0.PE=1后,CPU虽然进入保护模式,但CS寄存器仍然是实模式下的段值,没有加载对应的保护模式段描述符。此时直接给DS加载GDT条目会触发#GP(一般保护异常)——保护模式下加载段寄存器需要验证权限,而CS此时还是实模式的“伪描述符”,权限不匹配,无法完成数据段寄存器的加载。必须先通过远跳转让CS加载合法的保护模式代码段描述符,建立起有效的保护模式执行环境后,才能安全地加载其他段寄存器。
疑问3:代码执行两次远跳转,返回Unreal Mode时CS=8,与CS.base不匹配会破坏中断的CS:IP保存恢复机制,完全不使用远跳转是否可行?
可以完全不用远跳转,但要处理两个核心点:
- 进入保护模式时,用近跳转代替远跳转来刷新预取队列。近跳转不会修改CS的值,此时CS还是实模式的段值,但CR0.PE=1会让CPU把它当作一个兼容的保护模式段描述符(基地址=段值<<4,限长0xFFFF),后续加载DS的操作是合法的。
- 返回Unreal Mode时,直接修改CR0.PE=0即可,不需要远跳转。此时所有数据段寄存器已经加载了32位平坦段描述符,回到实模式后这些寄存器的隐藏部分会保留保护模式的设置(基地址0,限长4GB),这正是Unreal Mode的核心特性——数据段使用32位平坦模式,代码段保持实模式。
不过要注意,部分非常老旧的CPU(比如早期80386)对近跳转刷新预取队列的支持不佳,远跳转是兼容性更好的做法。但如果只针对较新的x86 CPU,完全可以不用远跳转,避免CS被修改导致的中断机制问题。
内容的提问来源于stack exchange,提问作者moehr1z
相关产品推荐
相关产品推荐

