常见错误

1. 切换保护模式后系统重启或死机

原因A: GDT配置错误

症状: 执行 jmp CODE_SEG:init_pm 后CPU重启。

解决: 仔细检查GDT描述符的每个字节:

  • 第0项必须全为0
  • 代码段访问字节 = 0x9A (10011010b)
  • 数据段访问字节 = 0x92 (10010010b)

原因B: 没有执行远跳转

症状: 进入保护模式后行为异常。

解决: 设置CR0的PE位后,必须执行远跳转来刷新流水线:

jmp CODE_SEG:init_pm    ; 远跳转,不能省略

原因C: 中断没有关闭

症状: 随机崩溃或重启。

解决: 切换前必须 cli:

cli                     ; 必须在切换之前关闭中断
lgdt [gdt_descriptor]

2. 32位模式下屏幕没有输出

原因: 使用了BIOS中断

症状: 代码执行但屏幕无变化。

解决: 保护模式下不能使用 int 0x10。必须直接写VGA显存:

mov ebx, 0xB8000
mov al, 'A'
mov ah, 0x0F
mov [ebx], ax

3. GDT描述符大小计算错误

原因: gdt_descriptor 中的大小字段

解决: 大小 = GDT总字节数 - 1:

gdt_descriptor:
    dw gdt_end - gdt_start - 1    ; 注意 -1
    dd gdt_start

4. 段选择子值错误

原因: 选择子应该是GDT中的字节偏移

解决:

CODE_SEG equ gdt_code - gdt_start  ; = 0x08 (第2个描述符)
DATA_SEG equ gdt_data - gdt_start  ; = 0x10 (第3个描述符)

不能直接用 1、2 —— 必须是字节偏移量。

5. 32位模式下栈未设置

原因: 忘记设置ESP

解决: 进入保护模式后重新设置栈:

mov ebp, 0x90000
mov esp, ebp