vga print helpers

main
pantonshire 1 year ago
parent 592826e8cd
commit bd3063a80d

@ -37,17 +37,17 @@ self_load:
; Panic if the partition / boot1 starting LBA overflows 16 bits.
or ebx, ebx
jnz panic
jnz panic_simple
ror eax, 16
or ax, ax
jnz panic
jnz panic_simple
ror eax, 16
; Calculate the boot1 end LBA and panic if it overflows 16 bits.
; n.b. ebx is zero before this so both bx and ebx can be used as the boot1 end LBA.
mov bx, ax
add bx, BOOT1_TOTAL_SECTORS
jc panic
jc panic_simple
; Panic if the boot1 end LBA is after the partition end LBA.
; If the upper 32 bits of the partition end LBA are nonzero, then it must be greater than our
@ -56,7 +56,7 @@ self_load:
jnz .end_lba_ok
; Compare the boot1 end LBA to the lower 32 bits of the partition end LBA.
cmp ebx, ecx
ja panic
ja panic_simple
.end_lba_ok:
@ -74,7 +74,7 @@ self_load:
mov ecx, ebx
call read_sector
jc panic
jc panic_simple
add ebx, 512
inc word [bp - 0x02]
@ -82,32 +82,15 @@ self_load:
.self_load_done:
mov ebx, cafebabe
; Check the magic bytes at the end of boot1.
push es
mov ebx, boot1_magic
call addr32_to_addr16
mov eax, es:[ebx]
hlt
call test_a20
add al, 0x30
mov byte fs:[0x0000], al
hlt
cmp dword es:[bx], BOOT1_MAGIC
pop es
jne panic_simple
pr_womble:
; Reveal the true nature of jen
xor bx, bx
.loop:
cmp bx, WOMBLE_LEN
jae .done
lea si, [womble + bx]
mov dh, [si]
mov di, bx
shl di, 1
mov byte fs:[di], dh
mov byte fs:[di + 0x01], 0x1f
inc bx
jmp .loop
.done:
hlt
jmp main
; Converts a 32-bit address to a 16-bit sector and offset.
@ -119,8 +102,7 @@ pr_womble:
; - cf: unset on success, set on failure
; Clobber: none
addr32_to_addr16:
push bp
mov bp, sp
fnstart
push es
push eax
@ -152,9 +134,8 @@ addr32_to_addr16:
.fail:
pop eax
pop es
pop bp
stc
ret
fnret
; Reads a single sector at the given LBA into memory.
@ -170,8 +151,7 @@ read_sector:
; head = temp % n_heads
; cylinder = temp / n_heads
push bp
mov bp, sp
fnstart
push es
push ebx
@ -203,8 +183,14 @@ read_sector:
.return:
pop ebx
pop es
pop bp
ret
fnret
panic_simple:
mov ax, 0x0003
int 0x10
mov word fs:[0x0000], 0x4f21
hlt
%if ($ - $$) > 512
@ -212,7 +198,183 @@ read_sector:
%endif
main:
; Set VGA mode
; https://mendelson.org/wpdos/videomodes.txt
mov ax, 0x0003
int 0x10
; Disable the cursor (don't want to look at the blink blink blink)
mov ax, 0x0100
mov cx, 0x3f00
int 0x10
mov word [GLOBALS + VGA_COL], 0x1f00
call vga_clear
mov ax, msg_boot1_loaded
mov cx, MSG_BOOT1_LOADED_LEN
call vga_println
call test_a20
test ax, ax
jnz .a20_enabled
mov ax, msg_a20_disabled
mov cx, MSG_A20_DISABLED_LEN
call vga_println
; TODO: enable a20
hlt
.a20_enabled
mov ax, msg_a20_enabled
mov cx, MSG_A20_ENABLED_LEN
call vga_println
hlt
; Clear the VGA text buffer.
; Arguments: none
; Return: none
; Clobber: none
vga_clear:
fnstart
push di
push es
push ax
push cx
mov ax, 0xb800
mov es, ax
mov ax, [GLOBALS + VGA_COL]
mov cx, VGA_WIDTH * VGA_HEIGHT
xor di, di
rep stosw
mov word [GLOBALS + TEXTBUF_LINE], 0
pop cx
pop ax
pop es
pop di
fnret
; Scroll the VGA text buffer up one line.
; Arguments: none
; Return: none
; Clobber: none
vga_scroll:
fnstart
push si
push di
push ax
push cx
push es
push ds
mov ax, 0xb800
mov ds, ax
mov es, ax
; Copy everything up one line.
mov cx, VGA_WIDTH * (VGA_HEIGHT - 1)
mov si, VGA_WIDTH * 2
mov di, 0
rep movsw
; Clear the last line.
mov ax, [GLOBALS + VGA_COL]
mov cx, VGA_WIDTH
mov di, VGA_WIDTH * (VGA_HEIGHT - 1) * 2
rep stosw
pop ds
pop es
; Decrement the current textbuf line if it's greater than 0.
mov cx, [GLOBALS + TEXTBUF_LINE]
xor ax, ax
sub cx, 1
cmovae ax, cx
mov [GLOBALS + TEXTBUF_LINE], ax
pop cx
pop ax
pop di
pop si
fnret
; Write one line to the VGA text buffer.
; Arguments:
; - ax: pointer to the string to print
; - cx: string length
; Return: none
; Clobber: ax, cx
vga_println:
fnstart
push si
push di
push dx
push es
cmp word [GLOBALS + TEXTBUF_LINE], VGA_HEIGHT
jb .scroll_done
call vga_scroll
.scroll_done:
mov si, ax
mov ax, VGA_WIDTH
cmp cx, ax
cmova cx, ax
mov di, VGA_WIDTH * (VGA_HEIGHT - 1) * 2
xor dx, dx
mov ax, [GLOBALS + TEXTBUF_LINE]
mov di, VGA_WIDTH * 2
mul di
mov di, ax
mov ax, 0xb800
mov es, ax
mov ah, [GLOBALS + VGA_COL + 1]
.loop:
or cx, cx
jz .done
mov al, [si]
mov es:[di], ax
add di, 2
inc si
dec cx
jmp .loop
.done:
inc word [GLOBALS + TEXTBUF_LINE]
pop es
pop dx
pop di
pop si
fnret
enable_a20:
fnstart
fnret
; Check whether the A20 line is enabled. Writes to the boot sector identifier.
; Arguments: none
; Return:
; - ax: 0 if A20 disabled, nonzero if A20 enabled
; Clobber: none
test_a20:
push bp
mov bp, sp
push gs
; Restore the boot sector identifier in case it was overwritten by anything.
@ -238,22 +400,20 @@ test_a20:
.return:
pop gs
pop bp
ret
panic:
mov ax, 0x0003
int 0x10
mov word fs:[0x0000], 0x4f21
hlt
womble db "jen is a womble!"
WOMBLE_LEN equ $ - womble
msg_boot1_loaded db "boot1 loaded. hello!"
MSG_BOOT1_LOADED_LEN equ $ - msg_boot1_loaded
msg_a20_enabled db "a20 enabled"
MSG_A20_ENABLED_LEN equ $ - msg_a20_enabled
msg_a20_disabled db "a20 disabled"
MSG_A20_DISABLED_LEN equ $ - msg_a20_disabled
msg_panic db "fuck"
MSG_PANIC_LEN equ $ - msg_panic
times 409600 db 0
cafebabe:
dd 0xfeedface
boot1_magic dd BOOT1_MAGIC
BOOT1_TOTAL_LEN equ $ - $$
BOOT1_TOTAL_SECTORS equ (BOOT1_TOTAL_LEN + 511) / 512

@ -6,6 +6,11 @@
%define EBDA_START 0x080000
%define BOOT1_MAGIC 0x544e4150
%define VGA_WIDTH 80
%define VGA_HEIGHT 25
; boot0 base stack frame variable offsets / globals
; (we use the same offsets once we copy the variables to the globals section)
; -------------------------------------------------------------------------------------------------
@ -29,3 +34,18 @@
%define GPT_SECTORS_LOADED 0x16
%define GPT_CURRENT_LBA 0x18
%define BOOT1_GPT_ENTRY_ADDR 0x1a
; Globals
; ------------------------------------------------------------------------------------------------
%define VGA_COL 0x1c
%define TEXTBUF_LINE 0x1e
%macro fnstart 0
push bp
mov bp, sp
%endmacro
%macro fnret 0
pop bp
ret
%endmacro

Loading…
Cancel
Save