常见错误
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], ax3. GDT描述符大小计算错误
原因: gdt_descriptor 中的大小字段
解决: 大小 = GDT总字节数 - 1:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; 注意 -1
dd gdt_start4. 段选择子值错误
原因: 选择子应该是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