Once the BIOS is loaded, it looks around for a bootable device by looking at the Boot Sector. If it finds one, it starts executing the program on it. That program can be a very small program of just a few lines of assembly code to a very powerful program like GRUB. This program is responsible to perform various checks and load the operating system.
Our first bootloader was a very tiny program which printed “Hello” on the screen and looped.
Our second, improved bootloader will enable 32-bit protected mode of the Intel 86 processor and print something using the VGA text. The 32-bit protected mode addresses memory by using Descriptor Tables. This commit adds a file bootloader/boot.asm
.
The contents of the bootloader are loaded on the address 0x7c00
in the RAM. Hence we use org 0x7c00
in out bootloader. Next we enable the A20
bit i.e. the 21st address line for the intel x86 processor and set the VGA text mode. All x86 processors are started in 16-bit real mode. To use 32-bit protected mode, we must set the lowest bit in the special CPU register cr0
. We set up our Global Descriptor Table, initialize segment registers and print some text in VGA mode while in protected mode.
Our third bootloader load the kernel. It is a convention of sorts to use physical address 0x100000
as the starting address for kernels and thus our bootloader will jmp
to it after switching to 32-bit protected mode. The bootloader can be found here.
To make things easier, we have automated the build process using GNU Make:
make # creates the build/bootloader/boot.bin and build/disk.img
make qemu # run the qemu emulator