首页 > 解决方案 > 更改为保护模式会导致三重故障

问题描述

我一直遇到一个问题,在长时间跳转到保护模式后,似乎在设置ss寄存器时,会导致三重故障。我的代码:

switch-to-32bit.asm

[org 0x7c00]
[bits 16]
switch_to_32bit:
    cli
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1 ; protected mode
    mov cr0, eax
    jmp CODE_SEG:init_32bit ; far jump

[bits 32]
init_32bit:
    mov ax, DATA_SEG ; 0x1000
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov ebp, 0x90000 ; setup stack
    mov esp, ebp

    call BEGIN_32BIT

gdt.asm

gdt_start:
    dq 0x0

gdt_code:
    dw 0xffff ; segment length
    dw 0x0 ; segment base
    db 0x0 ; segment base
    db 10011010b ; flags 
    db 11001111b ; flags
    db 0x0 ; segment base

gdt_data:
    dw 0xffff ; segment length
    dw 0x0 ; segment base
    db 0x0 ; segment base
    db 10011010b ; flags 
    db 11001111b ; flags
    db 0x0 ; segment base

gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

使用 运行此命令时bochs,控制台中会出现许多调试行,如下所示: 调试日志

有谁知道为什么设置ss寄存器会导致这个问题?或者,如果问题更深层次(我明白了SS.mode = 16 bit)?谢谢。

标签: assemblyx86protected-mode

解决方案


您的数据段描述符上有一个不正确的标志:10011010b应该是10010010b. 第 3 位应该是0表示一个数据段。

当您mov将值放入段寄存器时,它会检查它的有效性。DS只要您不尝试写入该段,将(可读)代码段描述符移动到 中是有效的(尽管不是可取的) 。但是,将该描述符移入 是无效的SS,因此这就是出错的指令。你可能会遇到一个#GP(0x10)异常,它会级联成三重故障。


推荐阅读