summaryrefslogtreecommitdiff
path: root/mbr/stage1.asm
diff options
context:
space:
mode:
Diffstat (limited to 'mbr/stage1.asm')
-rw-r--r--mbr/stage1.asm79
1 files changed, 79 insertions, 0 deletions
diff --git a/mbr/stage1.asm b/mbr/stage1.asm
new file mode 100644
index 0000000..ea51f22
--- /dev/null
+++ b/mbr/stage1.asm
@@ -0,0 +1,79 @@
+[org 0x7C00]
+
+_start:
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+ mov fs, ax
+ mov gs, ax
+
+ cli ;; Disable all interrupts
+ cld ;; Strings shall increment
+ mov [boot_drive], dl ;; Save the boot drive
+
+ mov si, boot_sig
+ call print_str
+ call enable_a20
+ call disk_load
+
+ jmp 0x0000:0x8000
+ hlt
+ jmp $
+
+;;
+;; Write a string to the screen
+;;
+;; [SI]: Base address of string
+;;
+print_str:
+ lodsb ;; Load *(SI++) -> AL
+ or al, al ;; Null byte?
+ jz .done ;; Yup, finish
+ mov ah, 0x0E ;; Print char
+ int 0x10 ;; BIOS call
+ jmp print_str ;; Loop again until NUL
+.done:
+ ret
+
+;;
+;; Enable the A20 gate to access the full
+;; 16 megs
+;;
+enable_a20:
+ in al, 0x92 ;; Check the state
+ test al, 2 ;; is it already set?
+ jnz .done ;; Yes, no need to re-enable
+ or al, 2 ;; No, enable it
+ out 0x92, al ;; Write the new value back
+.done:
+ ret
+
+DAP:
+ .size: db 0x10
+ .reserved: db 0x00
+ .count: dw 1
+ .buffer: dw 0x8000
+ .segment: dw 0
+ .lba_lo: dd 1
+ .lba_hi: dd 0
+disk_load:
+ mov si, DAP
+ mov ah, 0x42
+ mov dl, [boot_drive]
+ int 0x13
+ jc .disk_err
+ ret
+.disk_err:
+ mov si, disk_errmsg
+ call print_str
+.hang:
+ hlt
+ jmp .hang
+
+boot_sig: db "* beepboot stage0", 0x0A, 0x0D, 0x00
+disk_errmsg: db "[!] failed to read disk", 0x0A, 0x0D, 0x00
+boot_drive: db 0
+
+times 510 - ($ - $$) db 0
+dw 0xAA55