Page 1 of 1

Far jump goes crazy

Posted: Tue Jun 02, 2015 5:45 am
by Reichtangle
Hi! I was writing the code that should bring the CPU from real mode to protected mode,
starting from the GDT and then reloading the segments before the final jump to the next bootloader stage.

However the code doesn't behave as it should, because the far jump needed for reloading CS somehow
goes completely crazy and (as you can see below) CS isn't loaded with the correct value.
The GDT itself is correctly set (first thing I've check) as well as the GDTR structure pointer and its contents.

Code: Select all

    ;;
    ;; File assembled with NASM
    ;; Function called from C. Defined as:
    ;; extern void JumpToPrelude(struct GlobalDescriptorRegister* GDTR)
    ;;
    JumpToPrelude:
    Use16
    mov eax, cr3
    inc al
    mov cr3, eax

    mov eax, [esp + 4]
    lgdt [eax]

.ReloadSegments:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    jmp 0x0008:.Continue

.Continue:
    ;;
    ;; This halt is never reached.
    ;;
    hlt
    mov esp, 0x00010000
    mov ebp, esp

    mov eax, 0x00020000    
    jmp eax
This is what VirtualBox says after the far jump:

Code: Select all

VBoxDbg> r
eax=0000f734 ebx=0000b8d2 ecx=00005e8b edx=00005000 esi=0000660f edi=000075ff
eip=0000ff53 esp=00007bd8 ebp=0000468b iopl=0 nv up di pl zr na po nc
cs=f000 ds=0010 es=0010 fs=0010 gs=0010 ss=0010               eflags=00000046
Completely off-road, the virtual machine as well as me.

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 5:57 am
by iansjack
I suspect that you are getting an exception but haven't created an exception handler. What's the business with cr3 all about?

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:00 am
by Roman
I have the same question. What are you doing with CR3? And you've not shown us the GDT and GDTR structures. You've also not enabled the protection.

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:01 am
by glauxosdev
Hi,

I see you have mixed things up...
  • Enabling protected mode should not be in a call, because the call address is vanished, as the stack segment is altered
  • The bit to enable protected mode is the bit 0 of cr0
  • You should not use "inc al", but "or eax, 1", as the second will simply set bit 0
  • Just after setting protected mode you should jump, and only then set the segments.
Also:

Code: Select all

    mov eax, 0x00020000   
    jmp eax
Simply make it "jmp 0x00020000", what is the point of wasting an instruction and a register?

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:19 am
by Reichtangle
I've completely confused CR3 with CR0 :shock:
Thank you all.
Simply make it "jmp 0x00020000", what is the point of wasting an instruction and a register?
Actually some nasty opcode were generated with that. Also wasting EAX isn't much of a problem in this location.

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:22 am
by glauxosdev
Hi,

And I have forgotten, why don't you have "bits 32" or "use32" right after the jump?

Regards,
glauxosdev

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:45 am
by Octocontrabass
Reichtangle wrote:Actually some nasty opcode were generated with that. Also wasting EAX isn't much of a problem in this location.
You'll get nasty opcodes when you try to execute 16-bit code in 32-bit mode, or vice-versa. (You're also missing a "use32", which will cause strange things to happen.)
glauxosdev wrote:Enabling protected mode should not be in a call, because the call address is vanished, as the stack segment is altered
As long as you aren't trying to return from that call, you're fine. (C provides the _Noreturn keyword, which may be useful in this situation.)

Re: Far jump goes crazy

Posted: Tue Jun 02, 2015 6:59 am
by Reichtangle
True I forgot the Use32 either.
Also yes, that function will never return, since it passes the control to the next bootloader stage,
which is loaded at indeed at 0x00020000 (and requires also a new stack).

Re: Far jump goes crazy

Posted: Wed Jun 03, 2015 4:01 am
by glauxosdev
Hi,

I have some propositions for you. You should:
  • Read the wiki so you don't confuse registers and algorithms;
  • Learn better assembly (and C if you feel you aren't ready);
  • Learn assembler-specific directives.
Regards,
glauxosdev