When the x86 CPU is powered on, its EIP (The Instruction Pointer) is hardcoded to the address 0xFFFFFFF0
, which is the last 16 bits of memory. At this point, the CPU is in Real Mode, so it can execute an instruction starting from 0xFFFFFFF0
.
Real Mode and Protected Mode are two operating modes of the CPU. Real Mode is the early working mode of the CPU, while Protected Mode is the modern working mode. Real Mode appeared during the era of the 8086 CPU and runs on 16-bit instructions. However, 16-bit CPUs can only support up to 1MB of addressing (20 address lines), so as memory grew larger, the register size became 32 bits. This led to the introduction of Protected Mode, which is used to achieve larger space and more flexible memory access.
Unlike the addressing in Real Mode, which is segment << 4 + offset
, the addressing in Protected Mode is done through the segment:offset
in the logical address. The segment
acts as a selector to index into an entry in the GDT/LDT, and then the flags
determine if the current program can access that memory segment. If it can, the base
is extracted and added to the offset
to obtain the linear address. Finally, the linear address is translated into a physical address through a page table.
Modern CPUs still enter Real Mode when running the BootLoader in order to achieve software backward compatibility.
The 16-bit address starting from 0xFFFFFFF0
is called the Reset Vector. At this point, the BIOS moves itself to RAM for faster access during subsequent operations, and the motherboard manufacturer ensures that 0xFFFFFFF0
points to the address of the BIOS (usually a jmp
instruction). Thus, the BIOS starts running.
The BIOS scans different devices (hard drives, CD-ROMs, flash drives, etc.) and determines if they are bootable. This determination is usually made by checking the last two bytes (511 and 512 bytes) of the device's first sector to see if they are 0xAA55
(note the endianness, whether it is little-endian or big-endian). If they are, the device is bootable.
When the BIOS finds a bootable device, it copies the first sector of that device to 0x7c00
in RAM (512 bytes starting from 0x7c00
) and jumps to execute the copied program starting from 0x7c00
. This segment of code is usually called the Bootloader.
The Bootloader then loads the system kernel from 0x100000
in RAM. Basically, the kernel of almost all x86 operating systems is located at 0x100000
. During this process, the Bootloader or the operating system itself switches the CPU's operating mode from Real Mode to Protected Mode. Thus, our operating system is started.