"call" after switching to protected mode

I am trying to switch to protected mode in Intel x86.

I loaded my gdt with lgdt, set the flag P cr0 to 1 and all segments, but when I return from the function call, I cannot call any other function, or I get this error

qemu: fatal: Trying to execute code outside RAM or ROM at 0xfeeb7c5b

Here is my switch_to_pmode function:

gdtr:
.short      23  // limit
gdtr_base:
.long       0   // base

switch_to_pmode:
    movl $null_segment, %eax        // Address of the first byte of the GDT
    movl %eax, gdtr_base

    cli             // disable interrupts

    lgdt (gdtr)

    movl %cr0, %eax
    or $0x1, %eax
    movl %eax, %cr0         // Set the PE flag

    push $0x8
    push $reload_segments
    lret

reload_segments:
    movl $0x10, %eax
    movl %eax, %ds
    movl %eax, %ss
    movl %eax, %es
    movl %eax, %fs
    movl %eax, %gs

    ret

foo:
    ret

And my calls

_start:
    call switch_to_pmode
    call foo // <----- Ouch!

thank

+5
source share
2 answers

You need to make sure that the assembler translates the code after the protected mode switch as a 32-bit code with a directive .code32(or use32in nasm).

, . . esp - .

+3

CR0, PE, - , %esp, . , . , , , , , .

, lret , , . :

switch_to_pmode:
    # ... what you have ...

    movl %eax, %cr0
.code32
    ljmpl reload_segments

reload_segments:
    # ... what you have ...
    movl $pm_stack, %esp
    sti # perhaps

    # and then just go on with your startup code here
    call foo

Intel , 9 ( ), 9.9, , .

+3

All Articles