Unreal Mode Bootloader: Instructions After Far Jump Execute Incorrectly
Posted: Wed Nov 26, 2025 2:53 am
Hello,
I am working on a bootloader that enters Unreal Mode to use 32-bit registers while remaining in real mode. I am encountering a problem where far jumps (ljmp) appear to work correctly, but only the first instruction after the jump executes as expected — all subsequent instructions behave incorrectly.
Below is the section of my code that appears to cause the problem:
I load the segment descriptors and set up the stack beforehand using the following code:
This setup is required because this is stage 2 of the bootloader, which has been loaded by stage 1 at physical address 0x7E00.
After debugging with GDB, I observed that the long jump from real mode to protected mode works correctly, and the long jump from protected mode to Unreal Mode also works initially. However, after executing the first instruction popw %ds, subsequent instructions appear to be corrupted.
Below is the relevant GDB output:
I suspect that this issue may be related to segment or stack setup in Unreal Mode, but I am unable to determine the exact cause. Any guidance or suggestions on resolving this problem would be greatly appreciated.
Thank you for your time and assistance.
I am working on a bootloader that enters Unreal Mode to use 32-bit registers while remaining in real mode. I am encountering a problem where far jumps (ljmp) appear to work correctly, but only the first instruction after the jump executes as expected — all subsequent instructions behave incorrectly.
Below is the section of my code that appears to cause the problem:
Code: Select all
# --- Enter Unreal Mode ---
.enter_unreal_mode:
cli
pushw %ds
lgdt gdt_ptr
sgdt 0x1000
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
ljmp $0x08, $pm_start + 0x7E00
pm_start:
movw $0x10, %bx
movw %bx, %ds
movl %cr0, %eax
andl $0xFFFFFFFE, %eax
movl %eax, %cr0
ljmp $0x0, $unreal+0x7E00
unreal:
popw %ds
sti
retCode: Select all
# Set all segment registers to the loaded segment
cli
movw $0x07E0, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $0x8000, %sp
sti
After debugging with GDB, I observed that the long jump from real mode to protected mode works correctly, and the long jump from protected mode to Unreal Mode also works initially. However, after executing the first instruction popw %ds, subsequent instructions appear to be corrupted.
Below is the relevant GDB output:
Code: Select all
(gdb) break *0x7E65
Breakpoint 1 at 0x7e65
(gdb) continue
Continuing.
Breakpoint 1, 0x00007e65 in ?? ()
1: x/i $pc
=> 0x7e65: ljmp $0xfb1f,$0x7e6a
(gdb) stepi
0x00007e6a in ?? ()
1: x/i $pc
=> 0x7e6a: pop %ds
(gdb) stepi
0x00007e6c in ?? ()
1: x/i $pc
=> 0x7e6c: ret
(gdb) stepi
0x00007e6e in ?? ()
1: x/i $pc
=> 0x7e6e: add %cl,%chThank you for your time and assistance.