D Bare Bones: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
No edit summary
m ("16k" to "16 KiB")
Line 39: Line 39:
dd CHECKSUM
dd CHECKSUM


STACKSIZE equ 0x4000 ; 16k if you're wondering
STACKSIZE equ 0x4000 ; 16 KiB if you're wondering


static_ctors_loop:
static_ctors_loop:

Revision as of 16:17, 18 November 2014

Difficulty level

Beginner
Kernel Designs
Models
Other Concepts

In this Tutorial we will write a kernel in the D language and boot it.

WAIT! Have you read Getting Started, Beginner Mistakes, and some of the related OS theory?

Preface

The following tutorial assumes basic knowledge of a compiler, linker and assembler toolchain. It also of course assumes prior knowledge of the D programming language.

Overview

In this tutorial we will create a simple D kernel that prints 'D' on to the screen. The basic setup will consist of three files:

  • start.asm
  • kernel.main.d
  • linker.ld

start.asm

global start
extern main        ; Allow main() to be called from the assembly code
extern start_ctors, end_ctors, start_dtors, end_dtors

MODULEALIGN        equ        1<<0
MEMINFO            equ        1<<1
FLAGS              equ        MODULEALIGN | MEMINFO
MAGIC              equ        0x1BADB002
CHECKSUM           equ        -(MAGIC + FLAGS)

section .text      ; Next is the Grub Multiboot Header

align 4
MultiBootHeader:
       dd MAGIC
       dd FLAGS
       dd CHECKSUM

STACKSIZE equ 0x4000  ; 16 KiB if you're wondering

static_ctors_loop:
   mov ebx, start_ctors
   jmp .test
.body:
   call [ebx]
   add ebx,4
.test:
   cmp ebx, end_ctors
   jb .body

start:
       mov esp, STACKSIZE+stack

       push eax
       push ebx

       call main

static_dtors_loop:
   mov ebx, start_dtors
   jmp .test
.body:
   call [ebx]
   add ebx,4
.test:
   cmp ebx, end_dtors
   jb .body

    
cpuhalt:
       hlt
       jmp cpuhalt

section .bss
align 32

stack:
      resb      STACKSIZE

Assemble that with:

nasm -f elf -o start.o start.asm

kernel.main.d

module kernel.main;

extern(C) void main(uint magic, uint addr) {
        int ypos = 0; //Starting points of the cursor
	int xpos = 0;
	const uint COLUMNS = 80; //Screensize
	const uint LINES = 25;

	ubyte* vidmem = cast(ubyte*)0xFFFF8000000B8000; //Video memory address

	for (int i = 0; i < COLUMNS * LINES * 2; i++) { //Loops through the screen and clears it
			volatile *(vidmem + i) = 0;
	}

	volatile *(vidmem + (xpos + ypos * COLUMNS) * 2) = 'D' & 0xFF; //Prints the letter D
	volatile *(vidmem + (xpos + ypos * COLUMNS) * 2 + 1) = 0x07; //Sets the colour for D to be light grey (0x07)

	for (;;) { //Loop forever. You can add your kernel logic here
	}
}

You then compile that with:

gdc -nostdlib -nodefaultlibs -g -c -o kernel.main.o kernel.main.d

linker.ld

OUTPUT_FORMAT(elf32-i386)
ENTRY (start)

SECTIONS{
    . = 0x00100000;

    .text :{
        code = .; _code = .; __code = .;
        *(.text)
        *(.rodata)
    }

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

    .data ALIGN (0x1000) : {
        data = .; _data = .; __data = .;
        *(.data)
        start_ctors = .; *(.ctors)   end_ctors = .;
        start_dtors = .; *(.dtors)   end_dtors = .;
    }

    .bss : {
        sbss = .;
        bss = .; _bss = .; __bss = .;
        *(COMMON)
        *(.bss)
        ebss = .;
    }
    end = .; _end = .; __end = .;
}

Now finally you can link all of that with:

ld -T linker.ld -o kernel.bin start.o kernel.main.o

Your kernel is now kernel.bin, and can now be booted by grub.

Keep in mind that to add other classes, functions, enums, etc. You must add the D runtime.

Hopefully this has gotten you started on writing your operating system in the D programming language.

Further reading

D BareBone with 64 bit and ldc2