Page 1 of 1

Bootloader fails calling C function

Posted: Tue Sep 27, 2016 7:16 am
by plevexier
I have a small bootloader in real mode I'm playing with, it boots ok, I validated with bochs debugger, but it fails to call the C kmain function.

Code: Select all

bits 16
global _start
extern kmain

section .text

_start:
	cli
	mov ax, 07C0h		; Set up 4K stack space after this bootloader
	add ax, 288		; (4096 + 512) / 16 bytes per paragraph
	mov ss, ax
	mov sp, 4096

	mov ax, 07C0h		; Set data segment to where we're loaded
	mov ds, ax
	sti

        call kmain
Here's the kmain code:

Code: Select all

void kmain(void) {
	const char* string = "stage1 loaded\0";

	volatile char *video = (volatile char*)0xB8000;
	while( *string != 0 )
    	{
        	*video++ = *string++;
        	*video++ = 0x07;
    	}
}
And here's the .ld file:

Code: Select all

ENTRY(_start)
STARTUP(boot.o)
INPUT(kernel.o)

SECTIONS
{
   .text :
   {
	*(.text);
   }
}
OUTPUT_FORMAT(binary)
OUTPUT(myos.bin)
I'm building with:

Code: Select all

nasm -f elf -o boot.o boot.asm
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
i686-elf-gcc -T kernel.ld -o myos.bin -ffreestanding -O2 -nostdlib -lgcc
And then I do a floppy with

Code: Select all

dd if=/dev/zero of=floppy.img bs=512 count=2880
dd if=myos.bin of=floppy.img
When I debug in bochs, the "call kmain" doesn't point to the right address but I can't figure out why... Am I missing something obvious here?

Thanks for your help.

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 7:32 am
by Octocontrabass
plevexier wrote:Am I missing something obvious here?
Your bootloader runs in 16-bit mode, but your C compiler emits 32-bit code.

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 9:02 am
by plevexier
Octocontrabass wrote:Your bootloader runs in 16-bit mode, but your C compiler emits 32-bit code.

Ahah, that sure could explain it :)

A -m16 should be enough right? I just quickly tested but it still doesn't work. Gonna investigate more though.

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 9:48 am
by plevexier
Yes I retried with:

Code: Select all

i686-elf-gcc -m16 -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
I put:

Code: Select all

asm(".code16gcc\n");
At the top of the C file, but same result, the kmain is not called. I even added:

Code: Select all

void kmain(void) __attribute__((section(".text")));
to the C file, just in case, but still, the kmain code is not at the right address :

Code: Select all

----------------
IN: 
# kmain(void)
0x00007c43:  call   0x7e00

----------------
IN: 
0x00007e00:  add    %al,(%bx,%si)
0x00007e02:  add    %al,(%bx,%si)
...

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 10:05 am
by Octocontrabass
The BIOS loads one sector.

How big is one sector? How big is your code?

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 10:56 am
by plevexier
Octocontrabass wrote:The BIOS loads one sector.

How big is one sector? How big is your code?
Yes it's the issue, the boot sector is 512 bytes, not enough for the assembly + the C code... Now I see why most of the kernel out there use multiboot... lol

Thanks for your help.

Re: Bootloader fails calling C function

Posted: Tue Sep 27, 2016 7:34 pm
by FallenAvatar
plevexier wrote:Yes it's the issue, the boot sector is 512 bytes, not enough for the assembly + the C code... Now I see why most of the kernel out there use multiboot... lol

Thanks for your help.
Also, GCC can NOT output real mode code! This might happen to work, but anything else is likely to break randomly. GCC expects 32-bit PMode, or 64-bit Long Mode, (And both with Flat Segments, CS = DS = ES = SS = 0)

- Monk

Re: Bootloader fails calling C function

Posted: Wed Sep 28, 2016 12:02 am
by alexfru
You may want to try out my BootProg in combination with Smaller C.

Re: Bootloader fails calling C function

Posted: Wed Sep 28, 2016 9:24 am
by plevexier
tjmonk15 wrote:
Also, GCC can NOT output real mode code! This might happen to work, but anything else is likely to break randomly. GCC expects 32-bit PMode, or 64-bit Long Mode, (And both with Flat Segments, CS = DS = ES = SS = 0)

- Monk
Yes, it's a good point, my goal was only to start on real mode, get the memory map using int 15h and then switch to PM. I think i'll go the other way around, use multiboot, boot in PM, switch to real mode, get the mem map and then switch back.

Re: Bootloader fails calling C function

Posted: Wed Sep 28, 2016 9:25 am
by plevexier
alexfru wrote:You may want to try out my BootProg in combination with Smaller C.
Nice resources thanks.

Re: Bootloader fails calling C function

Posted: Wed Sep 28, 2016 12:06 pm
by Octocontrabass
tjmonk15 wrote:Also, GCC can NOT output real mode code! This might happen to work, but anything else is likely to break randomly. GCC expects 32-bit PMode, or 64-bit Long Mode, (And both with Flat Segments, CS = DS = ES = SS = 0)
GCC can output 32-bit code that expects to be running in 16-bit mode. It will run in real mode as long as the entire program's address space is under 64kB and CS=DS=ES=SS. (It'll also run in 16-bit protected mode, with similar limitations.)

It doesn't work by coincidence, it's a documented feature of GCC. It won't break as long as Linux continues to rely on it.

Re: Bootloader fails calling C function

Posted: Thu Sep 29, 2016 12:44 am
by FusT
If you're going to use multiboot to boot your kernel you don't need to switch back to real mode and do int 15h to get a memory map, you can simply get it form the multiboot structure.
See the multiboot spec.