Search code examples
assemblybootloaderosdev

Far jumping causes triple fault after PMode is enabled?


This stage of my bootloader is loaded at 0x7e0:0x0000. After some "debugging" I've discovered that the following code generates a triple fault after my far jump. If I move the hang (Yes, including the actual procedure itself) before the jump, it doesn't triple fault. Sorry I couldn't include less code. I'm just trying to make sure I'm providing enough code so the bug isn't missed.

Here's my code:

bits 16

jmp SetUpPMode

GTDData:
    dd 0
    dd 0
    ;Code Descriptor
    dw 0xFFFF
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
    ;Data Descriptor
    dw 0xFFFF
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
GTDEnd:

GDTPointer:
    dw (GTDEnd - GTDData) - 1
    dd GTDData

LoadGDT:
    lgdt [GDTPointer]
    ret

SetUpPMode:
    cli
    mov ax, 0x7E0
    mov ds, ax

    call LoadGDT

    mov eax, cr0
    or eax, 1
    mov cr0, eax

    jmp 0x8:main

bits 32

main:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov esp, 0x90000

    jmp hang

hang:
    ;cli
    hlt
    jmp hang

I bet the bug/error is blatantly obvious, but I just can't seem to find it. Could someone please point it out? (If it matters, I'm using Virtual Box)


Solution

  • You load the code and the data at 0x07E0:0x0000. Therefore, all the references that the assembler and linker make are based at 0x07E0:0x0000 - such as main, which may be 0x0020 or something.

    But your GDT has the Code Segment based to 0x00000000 - so the jmp 0x8:main would JMP to absolute address 0x00000020 or something - nowhere near where the code is at 0x00007E20 or wherever. Either change the base of the segments in the GDT, or change the code to work from a real mode segment of 0x0000.