I'm trying to switch to the protected mode in intel x86.
I've loaded my gdt with lgdt, set the P flag of cr0 to 1 and all the segments selectors but when I return from the function call, I can't 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 you
You need to make sure the assembler translates the code following the protected mode switch as 32 bit code, with a .code32
(or use32
in nasm) directive.
Additionally your return address after your protected mode routine is no longer valid. You cant really return to anything after that. Instead set esp to something useful and go on.
A move to CR0 that sets or clears PE must be immediately followed by a far jump to reload the PC, and then you must reload %esp
as well as all the segment registers. You need to do all of this before you touch the stack or enable interrupts. And (as drhirsch says) it's impossible to return from this operation, even if you pop the return address off before you invalidate the real-mode stack, because the return address is a real-mode address.
You appear to be trying to use lret
to reload the PC and simultaneously re-enable interrupts, but that won't work, because the stack pointer is invalid. Correct code would look something like this:
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
You should read Intel's system programming guide, particularly chapter 9 (machine initialization), especially section 9.9, which describes in detail how to do a protected mode switch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With