16

I am writing a kernel, so that i am starting with a hello world program in kernel.

I have written a hello world kernel in c++ and it compiles successfully.

But when i boot it, it does not show anything on screen.

What's wrong with this code?

link.ld

OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS{
. = 0x00100000;

.text :{
    *(.text)
}

.rodata ALIGN (0x1000) : {
    *(.rodata)
}

.data ALIGN (0x1000) : {
    *(.data)
}

.bss : {
    sbss = .;
    *(COMMON)
    *(.bss)
    ebss = .;
}
}

loader.asm

[BITS 32]

global start
extern _main

start:
    call _main
    cli 
    hlt

video.h

#ifndef VIDEO_H
#define VIDEO_H

class Video{
    public:
        Video();
        ~Video();
        void clear();
        void write(char *cp);
        void put(char c);
    private:
        unsigned short *videomem;
        unsigned int off;
        unsigned int pos;
};
#endif

video.cpp

#include "Video.h"

Video::Video(){
pos = 0;
off = 0;
videomem = (unsigned short*)0xb8000;
}

Video::~Video(){}

void Video::clear(){
unsigned int i;
for(i=0;i<(80*25);i++){
    videomem[i] = (unsigned short)' '|0x0700;
}
pos = 0;
off = 0;
}

void Video::write(char *cp){
char *str = cp, *ch;
for(ch=str;*ch;ch++){
    put(*ch);
}
}

void Video::put(char c){
if(pos>=80){
    pos = 0;
    off+=80;
}
if(off>=(80*25)){
    clear();
}

videomem[off+pos] = (unsigned short)c|0x0700;
pos++;
}

Kernel.cpp

#include "Video.h"
int _main(void){
Video vid;
vid.clear();
vid.write("Hello World!");
}

I am compiling it using this commands:

g++ -c video.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
g++ -c Kernel.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
nasm -f aout Loader.asm -o Loader.o
ld -T linker.ld -o Kernel.bin Loader.o Video.o Kernel.o

It does not give any errors.

If it is possible to debug, then please help me to how to debug.

I am booting it in virtual box.

Any help will be appreciated.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985

4 Answers4

12

If you want, you can check out the OS that was used as an example in my class this semester. It's done in c. We were using GRUB bootloader, and qemu to run stuff.

It is written pretty cleanly in increments, the first increment being precisely the "Hello world" OS, and the last increment containing everything from a complete shell, threads & processes and lots of other stuff. You can find examples of source codes, makefiles and linker scripts in there (from the simple ones to quite complex examples)

http://sourceforge.net/projects/oszur11/

I would also link to the script following the increments but that is, unfortunately, not in English.

Oh, and also, there's one increment dedicated especially to debugging there, but that's more for debugging the procedures made for your OS than debugging the OS as a whole (if I remember correctly, we were using two consoles, one with qemu and one with gdb connected to the OS running in the other one).

penelope
  • 8,251
  • 8
  • 45
  • 87
  • 1
    +1 for one of the most awesome "how to XYZ, step by step, for dummies" projects that I've seen in a while. Though I'm not interested at all in writing an OS, this project of yours will nevertheless take up my entire weekend... just because :-) – Damon Aug 20 '11 at 10:00
  • Um, i've been searching for a week and and this guide is the best think i've ever seen thank you so much – Trevor Rudolph Jan 14 '13 at 23:35
  • @TrevorRudolph this is so old :) I took this class ages ago. Nice to know it's still there, those really _were_ one of the best materials for any class ever. – penelope Jan 15 '13 at 10:47
  • learning to code a kernel is where you get down to the nitty gritty of software and hardware, the most basic link, i teach myself everything and i wanted a better experience with C but now im getting pulled into assembly, odd language, but i nly need enough to pass off to C functions – Trevor Rudolph Jan 15 '13 at 23:58
  • 1
    Nice! I have also posted some more minimalistic examples at: https://github.com/cirosantilli/x86-bare-metal-examples – Ciro Santilli OurBigBook.com Sep 14 '15 at 21:15
5

When a PC boots, the BIOS will load whatever is in the MBR at physical address 0x7c00 and then jumps to that address. So you should link your code starting at 0x7c00 instead of at 0x00100000.

So, changing your linker script as follows should solve the problem:

...
SECTIONS{
    . = 0x7c00;
    ...
}

EDIT: After looking at your code, I noticed some more problems. If you're not using a bootloader, there are some things you have to set up before you can start executing 32-bit code, most importantly, enabling protected mode. Here are some tutorials to help you on your way.

mtvec
  • 17,846
  • 5
  • 52
  • 83
2

Have you tried qemu? When making a tiny os at uni, it proved to be the best program for this type of stuff.

Alexander
  • 9,737
  • 4
  • 53
  • 59
0

For this to work you will have to either:

  • implement the multiboot standard in loader.asm and use GRUB. A multiboot file is an ELF file with special headers. Example.
  • implement a bootloader yourself. At the very minimum you will need to:
Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985