Page 1 of 1

Kernel compilition without -O flag results in garbage

Posted: Tue May 01, 2012 6:52 am
by fittipaldi
Hello friends,
I tried searching for this specific problem, but can't seem to find an answer to my problem. Nor can I find one on my own.

The situation: I am trying to write my own OS (just for learning purposes), nothing special. I've written my own bootloader, totally from scratch, I am not using GRUB, Lilo or anything else. This bootloader of mine, loads a C-written kernel, compiled using GCC (cross compiler, following the instructions from the OSDev Wiki).
The problem: when I compile the C code, I have to pass the -O flag to gcc. Otherwise, when my bootloader loads the kernel all I get is garbage written to the screen, instead of a small text, that it should print out. When I specify the -O flag, it works OK, until I start doing loops and some more serious programming, then it shows random errors (e.g. just stopping to work at some point, or printing garbage, or other random stuff).

The kernel is loaded at address 0x10000 and executed by the bootloader via "jmp 0x10000". Here is the kernel source code:

Code: Select all

void kmain() {
	clear_screen(); // my own function, it just clears the screen
	printf("Hello, cruel world! This is my OS!"); // my own function, assembly code writing to the video memory
	set_cursor_position(0,1); // again my own function, using out assembly to set the cursor

	// get start and end address of memory probe
	uint16_t end_address_memory_map = (uint16_t)*((uint16_t*)0x7bfb);
	uint16_t start_address_memory_map = 0x7e00;
	uint16_t memory_map_length = end_address_memory_map - start_address_memory_map;
	// print some info
	printf("Memory map start address %d and its end is at %d (length: %d).", start_address_memory_map, end_address_memory_map, memory_map_length);
	set_cursor_position(0,2);
}
Linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(kmain)
startaddr = 0x10000;
SECTIONS {
  .text startaddr : {
    code = .;
    *(.text)
    *(.rodata)
  }

  .data (startaddr + (data - code)) : {
    data = .;
    *(.data)
  }

  .bss (startaddr + (bss - code)) : {
    bss = .;
    *(.bss)
  }

  end = .;
}
Compilation commands:

Code: Select all

TOP := $(shell pwd)
MY_LD := /usr/src/cross/bin/i586-elf-ld
MY_GCC := /usr/src/cross/bin/i586-elf-gcc
GCC_FLAGS := -Wall -nostdinc -nostartfiles -nodefaultlibs -nostdlib -fno-builtin -c -O -masm=intel
$(MY_GCC) $(GCC_FLAGS) -o kernel/src/main.o kernel/src/main.c
$(MY_LD) -T $(TOP)/kernel/ld.script -o kernel/kernel.img  kernel/src/main.o kernel/src/console.o kernel/src/port.o
Like I said, this code works if the "-O" flag is there, otherwise I get garbage on the screen. But I don't want the -O flag, because it messes with my loops later.

Please, give me an idea what I am doing wrong and how to remove the "-O" flag.

Re: Kernel compilition without -O flag results in garbage

Posted: Tue May 01, 2012 7:10 am
by sandras
fittipaldi wrote:

Code: Select all

printf("Hello, cruel world! This is my OS!"); // my own function, assembly code writing to the video memory
Don't know'bout the problem, but Pink Floyd by any chance?

Re: Kernel compilition without -O flag results in garbage

Posted: Tue May 01, 2012 7:26 am
by bluemoon
fittipaldi wrote:But I don't want the -O flag, because it messes with my loops later.
This is not a valid reason to disable -O.
The compiler would only mess your thing if you do not tell it what you did. So the correct way is to cooperate with the compiler by using correct syntax, supplying attributes, clobber lists, etc.