Have you ever wondered what happens when you turn on your computer? Before the operating system loads, a tiny program called a bootloader takes charge. Let’s make one ourselves—from scratch—using C and Assembly. It sounds scary, but stick with me and you’ll be surprised how fun it can be!
TL;DR
A bootloader is a small program that runs when the computer starts. It lives in the first 512 bytes of your hard drive. We’ll write one using Assembly and C, compile it, and run it in a virtual machine. It’s a great way to learn how your computer boots up and loads an OS.
What Is a Bootloader?
When your computer powers on, it doesn’t just jump into Windows or Linux. It first looks at a very special part of your storage device—the Master Boot Record (MBR). This part has 512 bytes, and inside lives the bootloader.
The bootloader’s job is to prepare the system and load the operating system. It’s the bridge between your hardware and your OS.
Why Make Your Own?
Because it’s cool! And also because:
- You learn low-level programming.
- You understand how computers boot.
- You can build something entirely your own.
Plus, with C and Assembly, you’ll get to control the machine directly. It’s like being the wizard behind the curtain.
Tools You’ll Need
- NASM – The Netwide Assembler, to compile Assembly code.
- GCC – To compile C code.
- QEMU or VirtualBox – To test your bootloader safely.
- DD – To create bootable disk images.
Let’s Get Started
A bootloader must be exactly 512 bytes. That’s the size of the MBR. The last two bytes must be a “magic number”: 0x55AA. This tells the BIOS, “Hey! I’m a bootable sector!”
Step 1: Writing the Bootloader in Assembly
Create a file called bootloader.asm with the following code:
bits 16
org 0x7C00
start:
mov ah, 0x0E
mov al, 'H'
int 0x10
mov al, 'i'
int 0x10
jmp $
times 510 - ($ - $$) db 0
dw 0xAA55
Let’s break this down:
bits 16tells NASM we’re using 16-bit real mode.org 0x7C00is where BIOS loads the bootloader in memory.mov ah, 0x0Eandint 0x10are BIOS interrupts to print characters.jmp $loops forever.
It will just display “Hi” on the screen, then freeze (in a good way!).
Step 2: Compiling It
Use NASM to assemble it into a binary:
nasm -f bin bootloader.asm -o bootloader.bin
This produces a raw boot sector file. Let’s test it!
Testing in QEMU
Fire up QEMU with your new bootloader:
qemu-system-x86_64 -drive format=raw,file=bootloader.bin
If all goes well, it will display “Hi” and do nothing else. That’s perfect.
Adding C into the Mix
Assembly is powerful but tough. C can make things easier. But there’s a catch: you can’t just write C code and expect it to boot. You need a minimal runtime.
Step 1: Prepare a 2-Stage Bootloader
Our first 512-byte bootloader loads the second stage that’s written in C.
Update your bootloader.asm file to load a second file:
bits 16
org 0x7C00
start:
mov si, msg
.print:
lodsb
or al, al
jz load_stage2
mov ah, 0x0E
int 0x10
jmp .print
load_stage2:
mov ah, 0x02
mov al, 3
mov ch, 0
mov cl, 2
mov dh, 0
mov dl, 0
mov bx, 0x8000
int 0x13
jmp 0x0000:0x8000
msg db 'Stage 1 Bootloader',0
times 510 - ($ - $$) db 0
dw 0xAA55
This prints a message and loads sector 2–4 into memory, then jumps there. That will be our C code!
Step 2: Writing the Stage 2 in C
Create stage2.c:
void main() {
char *video = (char*) 0xB8000;
video[0] = '!';
video[1] = 0x0F;
while (1);
}
This writes “!” at the start of the screen and halts. Simple and effective.
Step 3: Compiling the C Code
We need special flags:
i686-elf-gcc -ffreestanding -m32 -c stage2.c -o stage2.o
i686-elf-ld -Ttext 0x8000 stage2.o -o stage2.bin --oformat binary
Then combine both boot stages into one disk image:
cat bootloader.bin stage2.bin > boot.img
Step 4: Test It Again
Let’s see it in action:
qemu-system-x86_64 -drive format=raw,file=boot.img
You should see your stage 1 message and then a nice “!” pop up. You’re now officially a boot wizard.
Tips and Gotchas
- Always keep your loader under 512 bytes.
- C needs a flat binary—no standard libs allowed!
- Use a cross compiler for consistent output (like
i686-elf-gcc).
These things will save you hours of screaming into your keyboard.
Where to Go From Here?
This is just the beginning. You can enhance your bootloader to:
- Load entire operating systems.
- Use advanced graphics modes.
- Support keyboard inputs.
- Access file systems like FAT.
Once you understand the basics, the sky’s the limit.
Final Thoughts
Building a bootloader is one of the most exciting low-level projects you can do. It gives you great insight into how computers really work. It’s challenging, but rewarding—and now you’re part of a rare club who truly understands the magic of booting up!
So go ahead—hack the boot. 🚀
