D Bare Bones

From OSDev Wiki
Jump to: navigation, search
Difficulty level
Difficulty 1.png
Beginner
Kernel Designs
Models
Other Concepts

The factual accuracy of this article or section is disputed.
Please see the relevant discussion on the talk page.

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?

Contents

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*)0xFFFF_8000_000B_8000; //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 -c kernel.main.d -o kernel.main.o -g

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

Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox