flat assembler
Message board for the users of flat assembler.

Index > OS Construction > From bootloader to kernel

Author
Thread Post new topic Reply to topic
Andy



Joined: 17 Oct 2011
Posts: 55
Andy 22 Jan 2012, 11:37
Hi guys,

After I read some tutorials I wrote some a simple bootloader. Well, doesn't make too many things, just display a message on the screen but it's ok for now. My question is how to call from asm bootloader the main function from kernel, that I intend to write it in C.

My bootloader looks like:
Code:
[BITS 16]
[ORG 0x7C00]            ;Set origin at 0x7C00

call SetScreenMode      ;Call procedure that set screen mode
call BootMsg            ;Call procedure that set the message on the screen
jmp $                   ;replace with the jump in kernel main function

SetScreenMode:          ;Set screen mode 3: text 80 x 25 16 color
mov ah, 0
mov al, 3
int 10h
ret

BootMsg:
mov dx, 0               ;Set dh and dl to 0, subsequently used to set cursor position
mov si, Message         ;Put in SI the pointer of message
NextChar:
mov al, [si]            ;Put in al the char
inc si                  ;si += 1
or al, al               ;check if value in al is 0
jz BootMsgOut           ;if al = 0 then jump to BootMsgOut label
call PrintChar          ;else call PrintChar procedure
jmp NextChar            ;go back and do same things for next chars
BootMsgOut:
ret

PrintChar
mov ah, 9               ;function code
mov bh, 0               ;page number
mov bl, 4               ;text color
int 10h                 ;call 10h interrupt
mov ah, 2               ;put function code in ah (to set cursor position)
inc dl                  ;dl += 1   next char position
int 10h                 ;call 10h interrupt
ret

Message db 'Bootloader...ok', 0

TIMES 510 - ($ - $$) db 0
DW 0xAA55    


Here is how looks like the bootloader in QEMU:
Image

Thanks in advance!
Post 22 Jan 2012, 11:37
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 22 Jan 2012, 13:38
As the name suggests, the boot loader will also need to load the kernel from disk into memory (temporary buffer); in the case of a C kernel, there are a few possibilities. Depending on your compiler/setup, the normal output is PE or ELF binaries which include a header that tells you the section offsets and sizes; you'll want to unpack the binary (to another location) according to these values and then jump to the entrypoint address (also in the header).

If your kernel is 32bit, the final image address must be what is specified in the header but in 64bit you can compile with position independent code (PIC) enabled and put the image anywhere. A few gotchas if you're aiming for a 64bit kernel are that VS does not allow 64bit inline assembly, so you'll need to create and link an external COFF file in FASM, and the fastcall convention is different between windows and unix compilers, so any calls into supporting FASM code will need to be (re)assembled accordingly.

For the actual jump from the loader to kernel, you have the choice of the jump that switches to protected/long mode going directly to the kernel entrypoint, and having to set up the correct register state in C (ASM still required here), or you can do this in the loader and jump again to the entry point.

Hope that helps.
Post 22 Jan 2012, 13:38
View user's profile Send private message Reply with quote
Andy



Joined: 17 Oct 2011
Posts: 55
Andy 22 Jan 2012, 14:57
Ok, what compiler you suggest me to use to get one of this output formats? Can you point me to some good resources or some simple examples?
Post 22 Jan 2012, 14:57
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 22 Jan 2012, 16:36
Without more information, I'd say probably GCC, which is multi platform and well supported by IDEs, if you want one. On unix the default output is ELF, on the windows MinGW port it is PE exe.

I don't have example code for loading the binary because I use FASM macros to merge it into my ASM module at compile time but you can lookup the PE/ELF header definitions and do this at run time. For a 64bit target, I use:
Quote:
gcc -nostdinc -O2 -Wall -Werror -c -fPIC -omain.o ../main.c -m64
gcc -nostartfiles -nodefaultlibs -nostdlib -o./release/main.run main.o -m64
to compile the top level C module. Because there is no stdlib, the entry point in main.c is now "void _start()" which is the equivalent of "int main(int,char*[])" in a normal program.
Post 22 Jan 2012, 16:36
View user's profile Send private message Reply with quote
egos



Joined: 10 Feb 2009
Posts: 144
egos 23 Jan 2012, 09:14
Usually stage 1 boot loader runs raw binary. So you should have kernel in raw binary format if it's run directly by stage 1. Or you should have stage 2 boot loader in raw binary format that is run by stage 1 and then runs kernel in ELF/PE format.
Post 23 Jan 2012, 09:14
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.