2 – Developing an Operating System – Tutorial – Episode 1 – BIOS, UEFI, Assembler, Boot loader and Hello World

We are going to learn to write a simple boot loader which will boot up our computer and display “Welcome to LearnOS” on screen. Before we start we need to understand what happens when we press a power button of a computer.

YouTube Video – Writing an Operating System – Episode 1 – Boot Loader

When we press a power button, power is given to the CPU, and CPU looks for a small program that is stored inside a chip which is on a motherboard. Program stored on a chip is called as BIOS (Basic Input/Output System) and on a newer motherboard it is called as UEFI (Unified Extensible Firmware Interface). We will currently focus on BIOS.

When BIOS boots up, BIOS loads configuration settings and initializes the system hardware. If you do not have any RAM (Random Access Memory) attached to a motherboard of a PC, BIOS will produce a beep sound and will stop the booting process. This is known as Power on Self Test (POST), BIOS also verifies that all components of the system has adequate power supplied to function. Once BIOS initializes all system hardware successfully, it will hand over the responsibility of booting your PC to operating system’s boot loader.

BIOS will go through each storage device attached to the computer or based on configuration in BIOS Setup / Settings and will look for the boot loader, once it finds boot loader BIOS will load boot loader into memory. Boot loader contains code that loads the rest of the operating system. On a hard disk it is Master Boot Record (MBR) and load it into memory. The MBR contains code that loads the rest of the operating system. For a simplicity we will not go into MBR right now but instead write a very simple boot loader, compile it and boot our system. So, Let’s get started.

If you are facing any issues executing commands watch a video which I have posted for the same on YouTube, You can find link for the videos at the bottom of this post.

Tools

  1. Any OS (Windows, Linux, MacOS, etc…)

    We will require an Operating System using which we will write our boot loader, compile and run it.

  2. Any Text Editor (Notepad, Notepad++, Visual Studio Code, vim, nano etc…)

    We will be using text editor to write our code.

  3. FASMhttps://flatassembler.net/ (Available for Windows, Linux, MacOS, etc…)

    This is a assembler, which will compile our code written in assembly language and give us binary output. Yes, we will write boot loader in assembly language. Do not worry, it is not going to be difficult.

  4. QEMUhttps://www.qemu.org/ (Available for Windows, Linux, MacOS, etc…)

    We will not take a risk of loading our boot loader on our main computer, rather we will be using Virtualization or Emulation to test our boot loader. We are going to use QEMU, it is easy, faster and FREE!!!

  5. Hex Editor / Viewer (Windows – https://mh-nexus.de/en/hxd/) – Hex editor / viewer is optional.

    This is optional, but it will help you understand what is going on.

If you would like to know how to setup above tools, you can watch a video which is posted on YouTube channel links for the same you can find at the end of this post.

FASM – How to Setup Flat Assembler (FASM) on Windows
QEMU – How to Setup QEMU on Windows

Usually 1st sector of a storage device is a boot sector, but BIOS specifies that boot sector should be 512 bytes long (One of the reason being inter-operability, another reason you will see shortly).

Let’s write our first boot sector.

Create a folder called LearnOS a blank file and give it a name boot.asm

Now, open command prompt (Windows) or terminal (Linux, MacOS) and go to the location of a folder / path where you have created boot.asm file.

Type following command on command prompt / terminal:

fasm {path_to_your_boot.asm_file}\boot.asm

If everything works fine, above code will show you output as follows:

FASM compilation output.

FASM produces the output boot.bin, if you notice the size of boot.bin it is 0 bytes same as boot.asm

Now, lets run this into QEMU by type following command on command prompt / terminal:

qemu-system-x86_64 boot.bin

You will be able to see QEMU window with following output:

As you can see in the above output we are getting an error: could not read the boot disk. This is because our binary file is 0 bytes and boot sector should be of size 512 bytes.

Let’s modify boot.asm file to write 512 bytes. We will fill it with 0. Type following code in boot.asm

times 512 db 0

Compile boot.asm

fasm {path_to_your_boot.asm_file}\boot.asm

you will see that the boot.bin file size is 512 bytes as expected by BIOS. If you open boot.bin file in hex editor, you will see 512 bytes contains 00.

Empty 512 bytes boot.bin file.

Now, lets run this into QEMU. Type following command:

qemu-system-x86_64 boot.bin

You will be able to see QEMU window with the following output:

Boot sector booting with not a valid signature.

Hmm, it is still not able to boot.. but did you notice a different error message? Earlier we had an error could not read the boot disk. Now we have an error not a bootable disk. Which means that we are able to write 512 bytes of code in boot sector, but what we have written is not identified by BIOS as a boot sector. BIOS look for specific 2 bytes at end of the sector for identifying the boot sector, this is called as Boot Sector signature, also known as the magic number, and magic number is 55AA, for this all we need to do is write 55 AA at end of the boot sector. 55 AA is two bytes and boot sector should be of 512 bytes so we will make changes in our code as follows:

times 510 db 0
dw 0xAA55

You will notice that signature is 55AA but we write it as AA55, this is because PC architecture is little-endian (Read more about Endianness), 55AA signature can also help us determine the CPU on which OS will run is little-endian or big-endian. Also notice that we changed times 512 to 510, because 2 bytes will be occupied by 55AA so we need only 510 bytes of 00s.

Now, if you compile above code and load it in QEMU you will see the machine is booting but it seems that it is stuck / hung:

Boot sector booting

Actually system is not hung, it is doing what we have written in code. We are just identifying our code as boot sector but not doing anything else. You must be wondering it is not taking any keyboard input as well, that is correct. Because we are not handling keyboard input in our OS yet. Yes, we need to do everything. Also notice the hex view of bin file (Notice the last two bytes):

Hex view of boot.bin with last two bytes showing boot signature.

Now, let us take it a step further into displaying Hello World on screen or better “Welcome to LearnOS“.

Code for same is as follows:

mov ah, 0eh ;tele prompt
mov al, 57h ;W
int 10h ;print
mov al, 65h ;e
int 10h
mov al, 6ch ;l
int 10h
mov al, 63h ;c
int 10h
mov al, 6fh ;o
int 10h
mov al, 6dh ;m
int 10h
mov al, 65h ;e
int 10h
mov al, 20h ;{space}
int 10h
mov al, 74h ;t
int 10h
mov al, 6fh ;o
int 10h
mov al, 20h ;{space}
int 10h
mov al, 4Ch ;L
int 10h
mov al, 65h ;e
int 10h
mov al, 61h ;a
int 10h
mov al, 72h ;r
int 10h
mov al, 6Eh ;n
int 10h
mov al, 4Fh ;O
int 10h
mov al, 53h ;S
int 10h

times 510-$ db 0
dw 0xAA55

We had to write a lot of repetitive code, there is better way to do what we have written above, but focus is not into assembly language but rather writing an operating system.

Did you notice second last line changed to times 510-$ db 0? What -$ means is that we want program so far to be 510 bytes so here we are calculating 510-$ ($ means size occupied till now), this may come to say 510-50, which means that line of code will write 00 to 460 bytes and after that 2 bytes will have boot signature.

Compile it, and run it. You should be able to see output as follows:

QEMU running LearnOS 😊

Now that looks great and brings a good smile on our face 😁

We conclude our learning of boot sector here, and in next blog we will move onto converting code into C language code, as I would not like to continue with Assembly language, it will end up become very complex and very lengthy. In next chapter we will also introduce few things into our operating system. There is also conception about 07c00 memory address, which we will discuss in next blog.

1 – Boot sector to handover control to Operating System or Kernel.
2 – Real mode and Protected mode.
3 – Starting to write Kernel.
4 – Take input from user using keyboard.
5 – Enumerate Devices attached to computer.

Videos:

FASM – How to Setup Flat Assembler (FASM) on Windows
QEMU – How to Setup QEMU on Windows
Writing an Operating System – Boot Sector

Github:

You can find source code on github @ https://github.com/dhavalhirdhav/LearnOS

About the Author

1 thought on “2 – Developing an Operating System – Tutorial – Episode 1 – BIOS, UEFI, Assembler, Boot loader and Hello World

Comments are closed.