Page 1 of 1

Why I can't call functions after jumping to new code sector

Posted: Fri Sep 19, 2014 2:11 pm
by Hanz
Hi.

I am starting OS developer. I just learned how to load new code with bootloader using assembly, but now I have a problem. I can't call functions after loading new bytes from floppy. I tried google, wiki.osdev.org and some other sites, but I didn't find anything.

I think there must be simple solution.

Here is my code:

Code: Select all

[BITS 16]
[ORG 0x7C00]

jmp Start

Start:
    ; booting up. pring message
    mov si, msg_first
    call print_first
    ; load more bytes from floppy and jump there
    call LoadKern


; Load kernel procedure
LoadKern:
        mov ah, 0x02    ; Read Disk Sectors
        mov al, 0x01    ; Read one sector only (512 bytes per sector)
        mov ch, 0x00    ; Track 0
        mov cl, 0x02    ; Sector 2
        mov dh, 0x00    ; Head 0
        mov dl, 0x00    ; Drive 0 (Floppy 1) (This can be replaced with the value in BootDrv)
        mov bx, 0x2000  ; Segment 0x2000
        mov es, bx      ;  again remember segments bust be loaded from non immediate data
        mov bx, 0x0000  ; Start of segment - offset value
.readsector:
        pusha
        mov al, 'S'
        mov ah, 0Eh
        int 10h
        popa
        int 0x13        ; Call BIOS Read Disk Sectors function
        jc .readsector  ; If there was an error, try again

        mov ax, 0x2000  ; Set the data segment register
        mov ds, ax      ;  to point to the kernel location in memory
        pusha
        mov al, 'Y'
        mov ah, 0Eh
        int 10h
        popa

        jmp 0x2000:0x0000       ; Jump to the kernel


print_first:
    lodsb
    mov bx, 0
    cmp al, 0
    jz done_first
    mov ah, 0Eh
    int 10h
    jmp print_first
done_first:
    ret

msg_first db "Loading system...", 0x0D, 0x0A, 0


times 510 - ($ - $$) db 0 ; fill sector (except 2 last)
dw 0xAA55
; master boot record over
jmp KERNEL
KERNEL:
    pusha
    mov al, 'S'
    mov ah, 0Eh
    int 10h
    popa
    pusha
    mov si, msg_ready
    call print
    popa

    call halt
halt:
    cli
    hlt
    jmp halt
print:
    lodsb
    mov bx, 0
    cmp al, 0
    jz done
    mov ah, 0Eh
    int 10h
    jmp print
done:
    ret

br db 0x0D, 0x0A, 0
msg_ready db "ready", 0x0D, 0x0A, 0

times 1024 - ($ - $$) db 0 ; fill sector

Thanks for the help in advance.

Re: Why I can't call functions after jumping to new code sec

Posted: Fri Sep 19, 2014 2:37 pm
by Gigasoft
The problem isn't that you can't call functions, it's that you are accessing msg_ready through a label which the assembler regards as being at a different address than where you really loaded it. Perhaps it's better to split this into multiple source files.

Re: Why I can't call functions after jumping to new code sec

Posted: Fri Sep 19, 2014 2:59 pm
by Hanz
How does that help assembler? And I think I can't use nasm %include for that, and I am doing it with "raw data" floppy. How do I tell to assembler how to link or something?

Re: Why I can't call functions after jumping to new code sec

Posted: Fri Sep 19, 2014 8:26 pm
by SpyderTL
Try this article and let us know if you still have questions...

http://wiki.osdev.org/Linkers

Re: Why I can't call functions after jumping to new code sec

Posted: Fri Sep 19, 2014 8:51 pm
by neon
You told the assembler that the origin should be set to 0x7c00 but then change the segment to 0x2000:0 yielding invalid label offsets. In other words, you are lying to the assembler. The preferred method to resolve this is to separate the programs into two separate modules as already suggested. The boot record should just be responsible for locating and executing a separate program. Alternatively, do not use the org directive and initialize your segments properly.

In addition :

1. You never reserve initial stack space; never assume SS:SP is valid.
2. You never fix CS:IP to what your software expects; never assume CS:IP=0x7c0:0.
3. You never set initial segments.
4. No error checking.

There is a simpler solution, and that is just subtracting an offset from the labels. But I assure you that is a terrible hack. You really need to drop the notion of always looking for the simplest solution. Rather, you should be looking for a good solution.

Re: Why I can't call functions after jumping to new code sec

Posted: Sun Sep 21, 2014 10:23 pm
by Hanz
Thank you very much.

After many hours of work, I finally made working bootloader and my first kernel is now working properly.

1. I now reserved stack space.
2. Fixed CS:IP