Back to homepage

PC boot loader

This page gives well documented code for a basic PC boot loader. The code will boot from a 3.5" floppy disk, 720 k or 1.44 Mb in size. You will need free net-wide assembler NASM to compile this code, and dd command that comes with every Linux/BSD operating system - to copy compiled code onto the boot sector of the boot diskette.

Compile and copy commands

Compile (in fact assemble) command used to produce binary file (.o) from assembly source (.s) file:
nasm PcBootLoader002.s -f bin -o PcBootLoader002.o

Ignore compilation warnings.

Copy compiled binary file to diskette boot sector:
dd if=PcBootLoader002.o bs=512 of=/dev/fd0

Boot loader assembly code

; This is minimal boot loader for PC's. 
; It loads 8 sectors (4 kb) from boot drive, then jumps to loaded code.
; Code is loaded in 64 kb segment separate from the one used by this loader.
; Version 0.02. GNU GPL version 3 or latter. Author: Miroslav C.

; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; !!! Use at your own peril. No warranty or suitability implied.         !!!
; !!! This program will overwrite your boot sector (and possibly drive). !!!
; !!! Therefore, use floppies or emulator when testing.			 !!!
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

[BITS 16]		; 16 bit code generation
[ORG 0x7C00]		; Origin location. 
			; BIOS loads the boot code (512 bytes-1 sector) 
			; stored on diskette / hard drive
			; from this RAM memory address onwards.



MainProgram:		; Label for the start of the main program
cli			; disable interrupts
mov ax,0x8000		; Setup the Stack Segment register
mov ss,ax		; stack segment = 8000, absolute address = 80000 h
mov sp,0xFFFF		; stack pointer = FFFF
sti			; enable interrupts
mov [BootDrive],dl	; save boot drive number

mov si, Message1	; load the string to be printed - "bootloader version"
call PrintMessage	; call the procedure to print

call LoadSystem		; go to 'load sectors to memory' subroutine
jmp JumpToSystem	; now jump to loaded system



LoadSystem:		; Loads 8 sectors from drive into memory
			; 9 sectors per track on 720 kb diskette
			; I got about 200 of those (in 2011),
			; and I plan on using them :)
mov si, Message2	; load the string to be printed - "resetting boot drive"
call PrintMessage	; call the procedure to print

.ResetDrive
mov ax,0x00		; function = reset disk
mov dl,[BootDrive]	; drive to be reset
int 0x13		; BIOS call to reset the drive
jc .ResetDrive		; if carry=1 (reset error), try again

mov ax,0x2000		; es:bx = sectors will be loaded here
mov es,ax		; es:bx = absolute address 20000 h
mov ax,0x0000
mov bx,ax		; bx=0x0000
			; es:bx = absolute address 20000 h + 00 h = 20000 h

mov si, Message3	; load the string to be printed - "loading sectors into memory"
call PrintMessage	; call the procedure to print

.LoadSystem
mov bx,0x00
mov ah,0x02		; function = read disk
mov al,0x08		; read 8 sectors (8*512 bytes = 4 kb). 
					; This works on 720 and 1440 kb 3.5 inch floppies.
mov cx,0x02		; sector 2
mov dh,0x00		; read head 0
mov dl,[BootDrive]	; read sectors from boot drive
int 0x13		; BIOS call to load sectors into memory at es:bx
jc .LoadSystem		; if carry=1 (read error), try again
ret			



JumpToSystem
mov si, Message4	; load the string to be printed - "jumping to loaded code"
call PrintMessage	; call the procedure to print

mov ax,0x2000
mov es,ax
mov ds,ax
jmp 0x2000:0000		; far jump to loaded system code in another 64 kb segment



PrintMessage:		; prints messages on screen
mov ah,0x0E		; function to display a character in "teletype" mode
mov bh,0x00		; page number
mov bl,0x07		; normal text attribute
.PrintMessage1
lodsb			; load string of bytes 
			; loads [SI] into AL and increases SI by one
 			; end of string is '0' 
or al,al		; sets the zero flag if al = 0 
jz .PrintMessage2	; zero flag = set: go to the end of the subroutine
int 0x10		; BIOS video interrupt to print character
jmp .PrintMessage1	; if more characters left to display, continue loop
.PrintMessage2
ret



; data
BootDrive db 0x00	; boot drive number 00=A 01=B 80=C 81=D
Message1 db 'M bootloader v.0.02',13,10,0
Message2 db 'Resetting boot drive.',13,10,0
Message3 db 'Boot drive reset. Now loading 8 sectors from drive into memory.',13,10,0
Message4 db 'Sectors loaded. Now jumping to loaded code.',13,10,0



; end magic number - to enable BIOS to recognize bootable sector
times 510-($-$$) db 0	; fill the unused sector bytes with zeros
dw 0xAA55		; boot loader magic number signature


Disclaimer

I'm not responsible for any damages that arise from the use of this code. 
Read through it and see what it does. 

Be especially careful with dd ("data destructor" :p) command.

Back to homepage