Let start at the beginning: the very first thing an OS needs is to boot.

Our first job will be to write a boot sector that just prints a startup message and then loops forever.

To do this, we have to know how a computer starts. When we power on a computer, the BIOS starts up, initializes internal data and sets up several hardware devices. Then, it perform power-on self tests (POST) and display system settings on screen. After this initialization phase, it looks at the sequence of bootable devices (floppy, CD, DVD, hard disk, USB stick, ...) into its configuration parameters. It tries to initiate the boot sequence from the first device. If the BIOS does not find a valid boot sector, it will try the next device in the list. A valid boot sector is one that has the two bytes 0xAA 0x55 at offset 510. If it does not find a proper boot sector on a device, the startup process will halt. Once the BIOS has found the bootable device, it reads its full boot sector (512 bytes) and puts it into memory at linear address 7C00h. Then it jumps to that address and lets the bootstrap code get control.

At this point, the CPU runs in Real Mode [1] and the content of its registers is undefined, except for DL which contains the BIOS number of the bootable device (00h for floppy, 80h for first hard disk, ...)

You can download the sources of this bootstrap in the ZIP archive attached to this note. I don't have set up a real workspace for the moment, so the archive contains only several assembly sources and a Windows batch file used to build the boot sector. I'll write soon a new note to describe my workspace. The only thing you need for the moment is a recent version of NASM. Moreover, you probably want to install a virtual machine software to avoid rebooting your PC too often. I'm using Virtual PC, but there are several others that are freely downloadable.

So let describe our boot loader.

The first thing we're doing is to set the data segment DS to the current segment (07C0h) so we won't have to add an 7C00h to all our data

    mov ax, 0x7c0
    mov ds, ax

Then we set up the stack. We need this because we will use the call instruction, which uses the stack. We install this stack 2000h bytes after our boot sector to have enough room (~8 KiB).

    mov ax, 0x9c0
    mov ss, ax
    mov sp, 0

The next step is to display the welcome message.

    mov si, boot_message
    call PrintMessage

The procedure PrintMessage reads each byte pointed by ds:si and invokes BIOS interrupt 10h to print the character to the screen. The loop stop when a null character is read.

PrintMessage:          
    mov ah, 0eh              ; 'put character' function
PM_loop:
    lodsb                   ; load byte at ds:si into al
    or al,al                ; test if character is 0 (end)
    jz PM_done
    int 0x10                ; invoke BIOS interrupt
    jmp PM_loop
PM_done:
    ret

Finally, the CPU falls into a infinite loop which has the effect to hang the PC. I have inserted a hlt instruction inside the loop to halt the CPU until the next interrupt. Hence, the loop consumes very few CPU power.

Notes

[1] This theme (and a lot of others) will certainly be developped in a future note.