Daniels NASM Bootstrap Tutorial

written by: Daniel Marjamäki
email: daniel.marjamaki@home.se
web:http://hem.passagen.se/danma/tuts.htm
Date: 2000-08-14


Introduction

This is what happens when a PC boots:
  1. The BIOS is executed
  2. The BIOS searches for a bootstrap
  3. When a bootstrap is found, it is loaded to memory address 07C00h
  4. The DL register is set to the drive number for the bootdrive.
  5. The Bootstrap, your code, is executed
A valid bootstrap MUST:


The Tools I use

These are the tools I use:
NASM - Assembler.
Helppc - Info about the interrupts.
Partcopy - To copy the bootstrap to the disk

These are all free of course.


Just hang...man!

This is a small example bootstrap. It just hangs:
hang:
	jmp hang

times 512-($-$$)-2 db 0
	dw 0AA55h
The "times.." line tells nasm that we want the file to be 512 bytes. The last two bytes in all bootstraps must contain 0AA55h, that is why I wrote that last line.

Compile with:
	nasm hang.asm -f bin -o hang.bin


If you want to test the bootstrap, you must transfer it to a disk. You will have to format the disk before you can use it again, so make sure there are no important information on it.
Transfer the file with:
	partcopy hang.bin 0 200 -f0


Reboot the computer with the disk inserted, the computer hangs!


Hello Cyberspace!

There were much joy when the computer hanged, but I am not content with this.
Now I will extend the bootstrap slightly. The bootstrap will print a message, and then hang.
The following code shows my improved bootstrap:
	org 0x7C00		; This is where BIOS put me

; ---------------------------------------------------------
; Main program
; ---------------------------------------------------------

	mov si, msg		; Print message
	call putstr

hang:				; Hang!
	jmp hang


; ---------------------------------------------------------
; Functions and variables used by our bootstrap
; ----------------------------------------------------------

msg	db 'Hello Cyberspace!', 0

; Print a 0-terminated string on the screen
putstr:
	lodsb		; AL = [DS:SI]
	or al,al		; Set zero flag if al=0
	jz putstrd		; Jump to putstrd if zero flag is set
	mov ah,0x0E	; Video function 0Eh
	mov bx,0x0007	; Color
	int 0x10
	jmp putstr		; Load characters until AL=0
putstrd:
	retn

times 512-($-$$)-2 db 0
	dw 0AA55h


The code is pretty easy, and I don't think I have to explain it.
Compile and transfer the bootstrap with:
	nasm hello.asm -f bin -o hello.bin
	partcopy hello.bin 0 200 -f0


A real real mode bootloader

The boot sector above was pretty cool, but it wasn't too useful. You'll want to create a boot sector that loads some program off the disk and jumps to it. The boot sector below is a real mode boot sector that loads stuff off the disk and jumps (the program is loaded to memory address 0x10000):

	org 0x7C00		; This is where BIOS put me

; ---------------------------------------------------------
; Main program
; ---------------------------------------------------------


start:
	; Setup the stack.
	; We can't allow interrupts while we setup the stack
	cli			; Disable interrupts
	mov ax, 0x9000		; Put stack at 0x90000
	mov ss, ax			; SS = 9000 and
	mov sp, 0			; SP = 0000 => Stack = 90000
	sti			; Enable interrupts

	; Remember the bootdrive information provided in DL
	mov [bootdrv], dl

	; Load a program
	call load

	; Jump to the loaded program
	mov ax, 0x1000
	mov es, ax
	mov ds, ax
	push ax
	mov ax, 0
	push ax
	retf


; ---------------------------------------------------------
; Functions and variables used by our bootstrap
; ----------------------------------------------------------

bootdrv	db 0			; This variable will contain the bootdrive id 


; Load a program from the bootdrive
load:
	; Reset the diskdrive (Interrupt 13h, 0)
	push ds			; Store DS
	mov ax, 0			; Select function (Reset Disk)
	mov dl, [bootdrv]		; Drive to reset
	int 13h			; Reset it!
	pop ds			; Restore DS
	jc loadfile			; Failed -> Try again

load1:
	mov ax,0x1000		; ES:BX = 10000
	mov es,ax
	mov bx, 0

	; Read disksectors (Interrupt 13h, 2)
	mov ah, 2			; Select function (Read disk sectors)
	mov al, 5			; read 5 sectors
	mov cx, 2			; Cylinder=0, sector=2
	mov dx, 0			; head=0, drive=0
	int 13h			; ES:BX = data from disk
	jc load1			; failed -> Try again

	retn

times 512-($-$$)-2 db 0
	dw 0AA55h

Now that our bootstrap loads and executes something, we _should_ write some code to load:

	mov ax, 1000h		; Update segment registers
	mov ds, ax
	mov es, ax

	mov si, msg		; Print a message
	call putstr

hang:				; Just hang
	jmp hang


; Print a 0-terminated string (SI=pointer to string)
putstr:
	lodsb
	or al,al
	jz short putstrd
	mov ah,0x0E
	mov bx,0x0007
	int 0x10
	jmp putstr
putstrd:
	retn

msg	db 'JIPPIKAYE!',13,10,0
Compile and transfer with:
	nasm bootload.asm -f bin -o bootload.bin
	partcopy bootload.bin 0 200 -f0
	nasm second.asm -f bin -o second.bin
	partcopy second.bin 0 200 -f0 200



Done

That's it. I would really like some comments.