Page 1 of 1

[SOLVED] Far jump in Bochs

Posted: Wed Aug 14, 2013 11:22 pm
by Vanzef
Hello, everybody!

I lost the fight with Grub2 http://forum.osdev.org/viewtopic.php?f=1&t=26967 :D So, I decided to roll my own bootloader for my custom kernel. As base I chose Linux kernel v0.01.

Here is a code of my bootloader:

Code: Select all

 
    .set    BOOTSEG, 0x7c0
    .set    LOADSEG, 0x9000
    .set    SYSSEG, 0x1000

start:
//copy the WHOLE bootloader to new location
    movw    BOOTSEG, %ax
    movw    %ax, %ds
    xor     %si, %si
    movw    LOADSEG, %ax
    movw    %ax, %es
    xor     %di, %di
    movw    256, %cx
    rep     movsw

//jump to new location
//enable A20
//    in      $0x70, %al
//    or      $0x2, %al
//    out     %al, $0x70

    movw    LOADSEG, %ax
    movw    %ax, %es
    ljmp      %es:loaded
//    pushw   LOADSEG
//    pushw   loaded
//    ret

loaded:
    jmp .
//set up data and stack
    movw    %cs, %ax        /*save new location*/
    movw    %ax, %ds        /*data segment starts here (cs)*/
    movw    %ax, %es
    movw    %ax, %ss        /*stack also starts there (cs)*/
    movw    $513, %sp       /*stack size > 512, not to clear our program)*/

//clear screen
    movw    $0x3, %ax
    int     $0x10

//print message
    pushw   msg
    pushw   $0xa
    call    print_msg

//load kernel to 0x10000
load_kernel:
    xor     %dx, %dx
    xor     %ah, %ah
    int     $0x13
    jc      reboot

    movw    SYSSEG, %ax
    movw    %ax, %es
    movb    $0x2, %ah
    movb    $1, %al
    movw    $0x1, %cx
    xor     %dx, %dx
    movw    $0x0, %bx
    int     $0x13
    jc      reboot

move_kernel:
    cli
    xor     %ax, %ax
    movw    %ax, %ds
    movl    $0x9000, %esi
    movw    %ax, %es
    movl    $0x0, %edi
    movl    (move_kernel_end-move_kernel), %ecx
    rep movsb
    sti
    jmp     $0x0
move_kernel_end:

print_msg:
//print message
    popw    %ax
    popw    %cx
    popw    %bp
    pushw   %ax
    movb    $0x04, %bl
    movb    $0x13, %ah
    movb    $0x1, %al
    int     $0x10
    ret

msg:
    .string "Booting..."

gdt_unreal:
    .quad   0x0

    .byte   0x0
    .byte   0b11001111
    .byte   0b10011010
    .byte   0x0
    .word   0x0
    .word   0xffff

    .byte   0x0
    .byte   0b11001111
    .byte   0b10010010
    .byte   0x0
    .word   0x0
    .word   0xffff
gdtr_unreal:
    .long   gdt_unreal
    .word   23

reboot:
    pushw   $0xdead
    pushw   $0x8
    call    print_msg

    .fill   510-(. - start), 1, 0
    .byte   0x55
    .byte   0xaa
I am using Bochs 2.6 with GDB-stub to run this code. So, it crashes while I wnat to jump to new location (%es:loaded).

Code: Select all

    movw    LOADSEG, %ax
    movw    %ax, %es
    ljmp      %es:loaded
Bochs output:

Code: Select all

[MEM0 ]   allocted_block: block=0x1 used 0x3 of of 0x200
[CPU0 ]   prefetch: EIP [00010000] > CS.limit [0000ffff]
[GDBST]   stopped with ac0
As I understood, Bochs says to me that I want jump to memory, which is higher than 1MiB. But 0x9000 is lower than 0xffff, isn't it? As I asid, the base was the Linux kernel v 0.01, Linus use `jmpi go, INITSEG` instruction to jump. Yasm doesn't undestand that instuction, so I use `ljmp` instead of it.

Question:
1) Is using `ljmp` instead of `jmpi` correct or not?
2) Why Bochs said that destination address is higher than 1MiB?

Thanks!

Re: Far jump in Bochs

Posted: Thu Aug 15, 2013 12:10 am
by HugeCode
Problem seems to be in your jump. I think that something like segreg:offset isn't actually allowed.
There are only two forms of far jump: absolute and absolute indirect. For direct jump, absolute immediate address (segment, offset) must be specified. Indirect jump gets new EIP value from address encoded with instruction. In think that your compiler uses indirect jump.

To solve your problem, you should try to use

Code: Select all

ljmp LOADSEG, $loaded
I'm not very familiar with AT&T.

About your error message, I can't see lgdt or switching to pmode anywhere, so it's difficult to explain why is your checked.

Re: Far jump in Bochs

Posted: Thu Aug 15, 2013 1:23 am
by Vanzef
Thanks, HugeCode!
I tryied

Code: Select all

ljmp $LOADSEG, $loaded
And it works!