Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 76 additions & 63 deletions boot.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,84 +5,97 @@
;;
;; Joe Bergeron, 2016.
;;
bits 16
bits 16 ; This sets the processor into 16-bit mode.

mov ax, 07C0h
mov ds, ax
mov ax, 07E0h ; 07E0h = (07C00h+200h)/10h, beginning of stack segment.
mov ss, ax
mov sp, 2000h ; 8k of stack space.
mov ax, 07C0h
mov ds, ax ; This sets the data segment (DS) to the address of the bootloader, which is 0x07C0.
mov ax, 07E0h ; 07E0h = (07C00h+200h)/10h, beginning of stack segment.
mov ss, ax ; This sets the stack segment (SS) to the address 0x07E0.
mov sp, 2000h ; This sets the stack pointer (SP) to the address 0x2000, giving us 8k of stack space.

call clearscreen
call clearscreen ; This calls the subroutine clearscreen, which clears the screen.

push 0000h
call movecursor
add sp, 2
push 0000h
call movecursor
add sp, 2 ; This sets the cursor to the top-left corner of the screen by calling the subroutine movecursor.

push msg
call print
add sp, 2
push msg
call print
add sp, 2 ; This prints the string "Oh boy do I sure love assembly!" to the screen by calling the subroutine print.

cli
hlt
cli
hlt ; These instructions disable interrupts and halt the processor, effectively freezing the computer.

clearscreen:
push bp
mov bp, sp
pusha

mov ah, 07h ; tells BIOS to scroll down window
mov al, 00h ; clear entire window
mov bh, 07h ; white on black
mov cx, 00h ; specifies top left of screen as (0,0)
mov dh, 18h ; 18h = 24 rows of chars
mov dl, 4fh ; 4fh = 79 cols of chars
int 10h ; calls video interrupt
; This is the subroutine clearscreen, which clears the screen by using BIOS interrupt 0x10. It saves the previous value of the stack pointer (SP) and the base pointer (BP), sets up a new stack frame, calls the interrupt, and then restores the previous stack frame and returns.

popa
mov sp, bp
pop bp
ret
clearscreen:
push bp ; Save the value of the base pointer (bp) on the stack
mov bp, sp ; Set the value of bp equal to the value of the stack pointer (sp)
pusha ; Push all the general-purpose registers (ax, bx, cx, dx, bp, si, di, and sp) onto the stack


mov ah, 07h ; Set the value of ah to 07h, which tells the BIOS to scroll down the window
mov al, 00h ; Set the value of al to 00h, which clears the entire window
mov bh, 07h ; Set the value of bh to 07h, which specifies white text on a black background
mov cx, 00h ; Set the value of cx to 00h, which specifies the top-left corner of the screen as the starting point
mov dh, 18h ; Set the value of dh to 18h, which specifies 24 rows of characters
mov dl, 4fh ; Set the value of dl to 4fh, which specifies 79 columns of characters
int 10h ; Call BIOS interrupt 10h, which clears the screen


popa ; Restore all the general-purpose registers from the stack
mov sp, bp ; Set the stack pointer equal to the base pointer, freeing the stack frame
pop bp ; Restore the value of the base pointer from the stack
ret ; Return from the subroutine



; This is the subroutine movecursor, which moves the cursor to the position specified by the argument passed on the stack. It saves the previous value of the stack pointer (SP) and the base pointer (BP), sets up a new stack frame, gets the argument from the stack, sets the cursor position using BIOS interrupt 0x10, restores the previous stack frame and returns.

movecursor:
push bp
mov bp, sp
pusha
push bp ; push base pointer onto stack to save its current value
mov bp, sp ; set base pointer to current stack pointer value
pusha ; push all general-purpose registers onto stack to save their current values

mov dx, [bp+4] ; get the argument from the stack. |bp| = 2, |arg| = 2
mov ah, 02h ; set cursor position
mov bh, 00h ; page 0 - doesn't matter, we're not using double-buffering
int 10h
mov dx, [bp+4] ; get the argument from the stack. |bp| = 2, |arg| = 2
mov ah, 02h ; set cursor position
mov bh, 00h ; page 0 - doesn't matter, we're not using double-buffering
int 10h ; invoke BIOS video interrupt to move cursor to specified position

popa
mov sp, bp
pop bp
ret
popa ; restore all general-purpose registers from stack
mov sp, bp ; restore stack pointer from base pointer
pop bp ; restore base pointer from stack
ret ; return from subroutine



; The "print" subroutine takes a pointer to a null-terminated string and prints the string to the screen.

print:
push bp
mov bp, sp
pusha
mov si, [bp+4] ; grab the pointer to the data
mov bh, 00h ; page number, 0 again
mov bl, 00h ; foreground color, irrelevant - in text mode
mov ah, 0Eh ; print character to TTY
push bp ; save the base pointer to the stack
mov bp, sp ; set the stack pointer to the base pointer
pusha ; push all registers onto the stack
mov si, [bp+4] ; grab the pointer to the data from the argument on the stack
mov bh, 00h ; set the page number to 0 (we're not using double-buffering)
mov bl, 00h ; set the foreground color to 0 (irrelevant in text mode)
mov ah, 0Eh ; set the print character function for TTY (teletype)
.char:
mov al, [si] ; get the current char from our pointer position
add si, 1 ; keep incrementing si until we see a null char
or al, 0
je .return ; end if the string is done
int 10h ; print the character if we're not done
jmp .char ; keep looping
mov al, [si] ; get the current character from our pointer position
add si, 1 ; increment the pointer to point to the next character
or al, 0 ; set AL to 0 if it's null
je .return ; if the string is done, end the subroutine
int 10h ; call the video interrupt to print the character
jmp .char ; keep looping until we reach the end of the string
.return:
popa
mov sp, bp
pop bp
ret


msg: db "Oh boy do I sure love assembly!", 0
popa ; restore all registers from the stack
mov sp, bp ; restore the stack pointer from the base pointer
pop bp ; restore the base pointer from the stack
ret ; return from the subroutine

times 510-($-$$) db 0
dw 0xAA55
msg: ; define the null-terminated string to print
db "Oh boy do I sure love assembly!", 0

times 510-($-$$) db 0 ; pad the bootloader to 510 bytes with zeros
dw 0xAA55 ; add the boot sector signature at the end