D Bare Bones II

From OSDev Wiki
Jump to: navigation, search

This tutorial needs to explain what the code does as tutorials are not just copy paste. You can help out by editing this page to include more context to what the code does.

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

Difficulty level
Difficulty 1.png
Beginner
Kernel Designs
Models
Other Concepts

In this Tutorial, we will continue to write the kernel in D, making a basic output to the console.

Contents

Overview

In this tutorial, we will continue to create our kernel on D, namely, we will make a minimal output to the console. Our file structure will be as follows:

  • 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;
import core.bitop;
 
extern(C): // We denote that all functions in our file will have the extern(C) flag
 
// Video memory address
const ubyte* vidmem = cast(ubyte*)0xFFFF_8000_000B_8000;
 
// Creating variables to indicate the cursor position.
// All global dynamic variables need to be marked with the shared flag, because there is no TLS in our kernel
shared int xpos = 0;
shared int ypos = 0;
 
// Creating a function to clear the console.
void clear() {
	for (int i = 0; i < 80*25*2; i++) {
		volatileStore(vidmem + i, 0);
	}
}
 
// Here we output the symbol passed to the function with the color as 0x07(light gray)
void putc_at(char symbol, int x, int y) {
    volatileStore(vidmem + x*2+y*160,symbol&0xFF);
    volatileStore(vidmem + x*2+y*160 + 1,0x07);
}
 
// Here we output a character with a check to see if it is a newline character.
void putc(char symbol) {
	if(symbol == '\n') {
		xpos=0;
		ypos+=1;
	}
	else {
		putc_at(symbol,xpos,ypos);
		xpos+=1;
		if(xpos==80) {xpos=0; ypos+=1;}
	}
}
 
// Here we output a string by looping through it
void puts(immutable(char*) str) {
	int counter = 0;
	while(str[counter] != 0) {
		putc(str[counter]);
		counter+=1;
	}
}
 
void main(uint magic, uint addr) {
 
	puts("Hello, world".ptr); // Output "Hello, world!" to the console
 
	for (;;) { //Loop forever. You can add your kernel logic here
 
	}
}

You then compile that with:

gdc -fno-druntime -m32 -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 -melf_i386 -T linker.ld -o kernel.bin start.o kernel.main.o

Your kernel is now kernel.bin, and can now be booted by grub, or run in qemu:

qemu-system-i386 -kernel kernel.bin
Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox