Creating an OS is no easy task, there are some challanges: * the build process - creation of the actual .bin or .iso file * coding low level features from scratch(FS, memory manager)
First, you should probably use Linux to achieve this goal because: * easy installation of tools * no linking problems
The tools we need are gcc(preinstalled), nasm for Intel Assembly or as(preinstalled), ld and qemu.
YOu can install each of them using sudo apt install <tool>
or using the mirrors for windows.
The languages we’ll be using are assembly and C.
The first file we will be creating is called the bootloader and it’s written in asm. It does the initialisation and creates a stack for the C code to follow.
.global bootmain
.extern kernmain
bootmain:
mov (%eax), 0
call kernmain
nothing:
nop
jmp nothing
# | IRQ stub will follow
# v
After that we can create a simple kernel.c file:
// no header will be included
char* buffer = (char*)0xb8000;
void kernmain()
{
*buffer++ = 'A';
*buffer++ = 2;
while(true) // equivalent to the nothing label in asm
asm('nop');
}
The address 0xb8000
represents the location of the video character buffer. Writing to it will output a letter(‘A’) with the color code 0x2.There is also a buffer for monochrome 0xb0000
and one for graphics(320x200) 0xa0000
.
Some tasks will include creating a memory manager using the MMU, a filesystem and process switching.
To interface with any other device, we will need functions to write to ports: inb/outb
.
Their deffinition involve using inline assembly:
char inb(short port) {
char data;
asm volatile("in %1,%0" : "=a" (data) : "d" (port));
return data;
}
void outb(short port, char data){
asm volatile("out %0,%1" : : "a" (data), "d" (port));
}
With this you can interface a timer(port 0x20), the keyboard(port 0x60), the IDE disk(ports 0x1f6/0x1f7) or the PCI controller(port 0xCF8)