更改为保护模式导致三重故障

Changing to protected mode causes triple fault

我一直有一个问题,在长时间跳转到保护模式后,似乎在设置 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)?谢谢。

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

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