Grumpy Developer's Prompt

OS Coding 1 - X86 Boot Sector in 16-bit REAL mode

Writing operating systems if fun if you’re nuts


What OS coding??

So you’ve always wanted to write your own operating system but never knew where to start? Welcome to the block kid! I mean you’re probably fairly old otherwise you wouldn’t want to do such a thing. After all OS coding is one of the worst things you can possible do to yourself.

Not only the sheer scale of the thing is daunting. The possible issues to overcome mind-boggling. The drivers… oh god the drivers.

But… if you’re really nuts then - OS coding is for you. At least that’s what I like to do when can’t sleep and the machine whispers to me. And there’s something to be said about people wanting to learn how it works really…

they die trying but hell… what a way to go!

Purpose of it all

The main purpose is to document my journey through this… coding. Some educational value might be there… somewhere… if you look deep enough.

I take no responsibility for any mental issues that might arise from reading this post!

Good references for later use

Requirements

Requirements that are to be installed. The list shows what was used for MacOS setup & compilation. I use MacOS so… brew, MacPorts are friends. For this part an X86 Assembly Compiler is needed as well as some CPU emulator (M1 is not Intel - we’re doing an X86 test boot sector). Bochs seems like a nice thing.

Requirement checkup

As stated, for testing our operating system we might use Bochs. Bochs is an X86 CPU emulator. One can use a vide variety of emulators but Bochs works nicely with text-based configuration files and the command line.

It works around configuration files. The simplest one tells it to load a particular binary image to a drive or our choosing.

We will need a boot sector image file but for now we can create an empty one:

touch boot_sect_empy.bin

and create a bochs configuration file as follows:

# Use the boot sector as though it were a floppy disk
floppya: 1_44=boot_sect_empty.bin, status=inserted
boot: a

save it as bochs.conf and run Bochs providing the configuration file we’ve just created:

bochs -f bochs.conf

Image alt

et voila! Bochs is running and panics saying that no bootable device has been found. Which is true since our boot sector is.. empty.

A good starting point so far!

Starting point - the boot sector itself

So what does the OS do at the very beginning? You insert an “iso” or other binary file as the starting disk/cd and something happens (back in the day we’ve inserted a floppy to disk A).

The BIOS (we’ll leave UEFI for later) reads the “boot sector”. A “boot sector” is a fixed amount of bytes that contains a small program that is executed by BIOS.

Usually the boot sector is just a starting point, a “bootstrap” that is used to setup the OS, setup the disk read operations so that a more “robust” version of the OS will be loaded later.

So whatever we want our OS to be a boot sector it needs.

Image alt

Here you can see a simple boot sector. You can get HexFiend or some other hex editor to create a binary file in such a way where you can control the bytes directly.

Testing in Bochs

If have stored our boot sector (written above) to boot_sect_simple.bin we can modify our configuration file for Bochs so that it loads a different binary file as the booting device:

# Use the boot sector as though it were a floppy disk
floppya: 1_44=boot_sect_simple.bin, status=inserted
boot: a

and run Bochs again:

bochs -f bochs.conf

Image alt

So now we get no info on the missing boot device? So that’s… good? Our program actually loops forever. So we see nothing. Sometimes seeing no error is good news as is in this case.

The three bytes at the very beginning of the boot sector include one of the smallest machine programs ever.

Coding the simplest boot sector in the assembly language

The simplest boot sector binary image that works we’ve coded by hand. In machine code. Not something a sane person would do.

The less-insane thing would be to code the same thing in assembly (before we move to something more human-friendly).

The following is a simple ASM program that loops forever and instruct the asembler to fix padding so that we get a nice 512-bytes file and add the magic number at the very end of the file:

;
; Boot sector program loops forever
;

loop:
    jmp $                       ; simply jump to the same line forever

padding:
    times 510-($-$$) db 0       ; add padding so we get a nice 512 bytes
    dw 0xaa55                   ; add magic numbers at the end

Once we save that to boot_sect_loop.asm we can compile using nasm:

nasm loop.asm -f bin -o boot_sect_loop.bin

We get something similar to what we’ve created ourselves by hand:

EB FE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
55 AA

Once we run Bochs we should get the same - no error - situation. Huzzah! A boot sector operating system with no functionality is born!.

Image alt

Yes, yes… we’ll get to do more “fun” things later.

References

#operating systems #os coding #x86