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
(update D code to use volatileStore and update commands to assume a non-i386 compilation environment)
Line 90: Line 90:
<source lang="d">
<source lang="d">
module kernel.main;
module kernel.main;
import core.bitop; // will be core.volatile in later gdc

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

ubyte* vidmem = cast(ubyte*)0xFFFF_8000_000B_8000; //Video memory address
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
for (int i = 0; i < COLUMNS * LINES * 2; i++) { //Loops through the screen and clears it
volatile *(vidmem + i) = 0;
volatileStore(vidmem + i, 0);
}
}

volatile *(vidmem + (xpos + ypos * COLUMNS) * 2) = 'D' & 0xFF; //Prints the letter D
volatileStore(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)
volatileStore(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
for (;;) { //Loop forever. You can add your kernel logic here
}
}
Line 113: Line 114:
You then compile that with:
You then compile that with:


<source lang="bash">gdc -c kernel.main.d -o kernel.main.o -g</source>
<source lang="bash">gdc -fno-druntime -m32 -c kernel.main.d -o kernel.main.o -g</source>


==linker.ld==
==linker.ld==
Line 153: Line 154:
Now finally you can link all of that with:
Now finally you can link all of that with:


<source lang="bash">ld -T linker.ld -o kernel.bin start.o kernel.main.o</source>
<source lang="bash">ld -melf_i386 -T linker.ld -o kernel.bin start.o kernel.main.o</source>

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


<source lang="bash">qemu-system-i386 -kernel kernel.bin</source>
Your kernel is now kernel.bin, and can now be booted by grub.


Note the "-fno-druntime" argument above. This is how gdc spells the -betterC flag from other D compilers, and the "Better C" page of the D language reference explains how this limits the language. If you want to drop that you'll have to add the D runtime to your kernel.
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.
Hopefully this has gotten you started on writing your operating system in the D programming language.

Revision as of 09:26, 19 November 2019

The factual accuracy of this article is disputed.
Please see the relevant discussion on the talk page.
This tutorial is not explained enough.
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

Beginner
Kernel Designs
Models
Other Concepts

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

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;
import core.bitop; // will be core.volatile in later gdc
 
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
			volatileStore(vidmem + i, 0);
	}
 
	volatileStore(vidmem + (xpos + ypos * COLUMNS) * 2, 'D' & 0xFF); //Prints the letter D
	volatileStore(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 -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

Note the "-fno-druntime" argument above. This is how gdc spells the -betterC flag from other D compilers, and the "Better C" page of the D language reference explains how this limits the language. If you want to drop that you'll have to add the D runtime to your kernel.

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