Merge branch 'refactor' into 'master'

Refactor

See merge request ZeusWPI/ass_messages!1
This commit is contained in:
j 2021-10-05 12:31:00 +00:00
commit ab6cede5b7

View file

@ -1,9 +1,12 @@
org 0x7C00 org 0x7C00 ; The boot code on a drive always gets loaded at address 0x7C00
bits 16 bits 16 ; .bin defaults to 16 bits
WIDTH equ 0x50 WIDTH equ 0x4F ; 79
HEIGHT equ 0x18 HEIGHT equ 0x18 ; 24
VIDEO_MODE equ 0x3 VIDEO_MODE equ 0x3 ; 80x25 screen, text mode
PIT_MODECOMMAND_PORT equ 0x43 ; programmable interval timer mode/command port (used for speaker)
PIT_CH2_DATA_PORT equ 0x42 ; PIT channel 2 data port
;; see http://www.ctyme.com/intr/int-10.htm for interrupts ;; see http://www.ctyme.com/intr/int-10.htm for interrupts
@ -13,173 +16,233 @@ mov ax, VIDEO_MODE
int 10h int 10h
;; Clear screen ;; Clear screen
mov ah, 0x06 mov ah, 0x06 ; scroll screen up
mov al, 0x00 mov al, 0x00 ; lines to scroll (0 = clear)
mov bh, 0x0F mov bh, 0x0F ; bg/fg colour
mov cx, 0x0000 mov cx, 0x0000 ; upper row number, left col number (both 0)
mov dh, HEIGHT mov dh, HEIGHT ; lower row number (24)
mov dl, WIDTH mov dl, WIDTH ; right col number (80)
int 0x10 int 0x10
;; Set cursor to bottom of screen ;; Set cursor to bottom of screen
mov dh, HEIGHT mov ah, 0x02 ; set cursor position
mov dl, 0x00 mov bh, 0x00 ; page number
mov bh, 0x00 mov dh, HEIGHT ; row (bottommost row)
mov ah, 0x02 mov dl, 0x00 ; col (leftmost col)
int 0x10 int 0x10
mov sp, 0x2000
mov sp, 0x2000 ; initialise stack pointer
.loop: .loop:
;; Read character mov ah, 0x00 ; Read a character
mov ah, 0x00
int 0x16 int 0x16
cmp al, 0x0d ; newline cmp al, 0x08 ; backspace
je .newline je change_color_mode
cmp al, 0x08 ; delete character
je .change_color_mode
cmp al, 0x1b ; escape character
je .beep
jmp .nonewline
.change_color_mode: cmp al, 0x1b ; esc
call .readbyte je beep
mov [color_mode], al
cmp al, 0x0d ; enter
je .nl
jmp nonewline ; all other characters
.nl:
call newline
jmp .loop jmp .loop
.newline: ;; Update the color_mode variable with a byte from the keyboard
;; Scroll up window ;;
mov ah, 0x06 ;; CLOBBERS
mov al, 0x01 ;; - ax
mov bh, 0x0F ;; - bl
mov cx, 0x0000 change_color_mode:
mov dh, HEIGHT call readbyte ; get byte from keyboard (in al)
mov dl, WIDTH mov [color_mode], al ; store byte in color_mode variable
int 0x10
;; Get current cursor position jmp start.loop
mov bh, 0x00
mov ah, 0x03 ;; Simulates going to a new line
;;
;; CLOBBERS
;; - ax
;; - bh
;; - cx
;; - dx
newline:
;; Scroll up window
mov ah, 0x06 ; scroll screen up
mov al, 0x01 ; lines to scroll (1)
mov bh, 0x0F ; bg/fg colour
mov cx, 0x0000 ; upper row num/left col num (both 0)
mov dh, HEIGHT ; lower row num (24)
mov dl, WIDTH ; right col num (80)
int 0x10 int 0x10
;; Move cursor to beginning of screen ;; Move cursor to beginning of screen
mov dl, 0x00 mov ah, 0x02 ; set cursors position
mov ah, 0x02 mov bh, 0x0 ; page number
mov dh, HEIGHT ; row
mov dl, 0x00 ; col
int 0x10 int 0x10
jmp .loop ret
.beep: ;; Plays a note on the speaker for a given duration
call .readduration ;;
mov ah, 0 ;; CLOBBERS
push ax ;; - ax
mov al, 182 ; Prepare the speaker for the ;; - bx
out 43h, al ; note. ;; - cx
call .readbyte beep:
call read_duration ; get duration from keyboard (in al)
mov ah, 0 mov ah, 0
push ax ; store on stack
;; move 182 (0b10 11 011 0) into al
;; bit 7-6 = channel select (2, PC speaker)
;; bit 5-4 = access mode (lobyte/hibyte)
;; bit 3-1 = operating mode (square wave generator)
;; bit 0 = BCD/binary mode (16-bit binary)
mov al, 0b10110110
out PIT_MODECOMMAND_PORT, al ; write to PIT control port
;; Read byte and convert to a usable frequency
call readbyte ; read byte from keyboard (in al)
mov ah, 0 ; readbyte clobbers ax
sal ax, 5 ; multiply by 32 sal ax, 5 ; multiply by 32
add ax, 1140 add ax, 1140
out 42h, al ; Output low byte.
mov al, ah ; Output high byte. out PIT_CH2_DATA_PORT, al ; Output low byte.
out 42h, al mov al, ah
in al, 61h ; Turn on note (get value from out PIT_CH2_DATA_PORT, al ; Output high byte
; port 61h).
or al, 00000011b ; Set bits 1 and 0. ;; Port 0x61 does a whole lot but only the bottom 2 bits are relevant here
out 61h, al ; Send new value. ;; (speaker enable and speaker input select)
in al, 61h ; Preserve previous value
or al, 00000011b ; Set bits 1 and 0 (enable speaker, input = channel 2)
out 61h, al ; Send new value
;; mov bx, 50000 ; Pause for duration of note. ;; mov bx, 50000 ; Pause for duration of note.
pop bx
push ax ;; multiply duration by 3125
pop bx ; pull duration value from stack into bx
push ax ; save ax (contains garbage?)
mov ax, 3125 mov ax, 3125
mul bx mul bx
mov bx, ax mov bx, ax ; move dur * 3125 into bx
pop ax pop ax ; restore ax
;; play note for a certain duration
.pause1: .pause1:
mov cx, 65535 mov ecx, 65535
.pause2: .pause2:
dec cx dec cx ; count down
jne .pause2 jne .pause2 ; if not zero keep counting down
dec bx
jne .pause1
in al, 61h ; Turn off note (get value from
; port 61h).
and al, 11111100b ; Reset bits 1 and 0.
out 61h, al ; Send new value.
jmp .loop
dec bx ; decrement duration counter
jne .pause1 ; keep doing that until it is 0
.nonewline: in al, 61h ; Preserve previous value
and al, 11111100b ; Clear bits 1 and 0 (disable speaker, clear channel select)
out 61h, al ; Send new value
jmp start.loop
;; Handles all other characters by writing them to the screen
;;
;; CLOBBERS
;; - ah
;; - bx
;; - cx
;; - dx
nonewline:
;; Write character ;; Write character
mov ah, 0x09 mov ah, 0x09 ; write character with attribute
mov bh, 0x00 mov bh, 0x00 ; page number
mov bl, [color_mode] mov bl, [color_mode] ; BIOS colour code
mov cx, 0x01 mov cx, 0x01 ; amount of times to print character
int 0x10 int 0x10
;; Get current cursor position ;; Get current cursor position
mov ah, 0x03 ;; dh = row, dl = col
mov ah, 0x03 ; get cursor position and shape
int 0x10 int 0x10
;; if the cursor is at the edge of the screen go to the next line
;; else move it forward once
cmp dl, WIDTH cmp dl, WIDTH
jge .eol jge .eol
jmp .noeol jmp .noeol
.eol: .eol:
;; Scroll up window call newline
mov ah, 0x06
mov al, 0x01
mov bh, 0x0F
mov cx, 0x0000
mov dh, HEIGHT
mov dl, WIDTH
int 0x10
;; Move cursor to beginning of screen jmp start.loop
mov bh, 0
mov dh, HEIGHT
mov dl, 0x00
mov ah, 0x02
int 0x10
jmp .loop
.noeol: .noeol:
;; Move cursor forward ;; Move cursor forward
inc dl inc dl
mov ah, 0x02 mov ah, 0x02 ; set cursor position, dh (row) already set, dl (col) updated on prev line
int 0x10 int 0x10
jmp .loop
jmp start.loop
.readbyte: ;; Reads two characters from the keyboard buffer and converts them into a single byte
;; Read character ;;
mov ah, 0x00 ;; The conversion happens as follows:
;; ASCII 'a' is subtracted from each character (so 'a' = 0, 'b' = 1, ...)
;; the first character is shifted left by 4
;; the shifted and non-shifted values are then or'ed together to form a byte
;;
;; RETURNS
;; A byte in al
;;
;; CLOBBERS
;; - ax
;; - bl
readbyte:
mov ah, 0x00 ; Read character
int 0x16 int 0x16
;; Read character is in al ;; Read character is in al
sub al, 'a' sub al, 'a' ; Normalise
mov bl, al mov bl, al
shl bl, 0x4 shl bl, 0x4 ; First character is upper 4 bits
;; Read character mov ah, 0x00 ; Read character
mov ah, 0x00
int 0x16 int 0x16
;; Read character is in al ;; Read character is in al
sub al, 'a' sub al, 'a' ; Normalise
or al, bl
or al, bl ; Combine both characters
ret ret
.readduration: ;; Reads a duration from the keyboard
;;
;; RETURNS
;; A duration in al
;;
;; CLOBBERS
;; - ax
read_duration:
;; Read duration (0-16 supported) ;; Read duration (0-16 supported)
mov ah, 0x00 mov ah, 0x00 ; read keypress
int 0x16 int 0x16
;; Read character is in al ;; Read character is in al
sub al, 'a' sub al, 'a' ; normalise
ret ret
halt: hlt ;; Variable to store color mode information for writing to the screen
color_mode: db 0x02 color_mode: db 0x02
;; Magic number must be in the last 2 bytes of the sector so
;; fill the binary with zeroes until it is 510 bytes in size
;; (magic number will use up the remaining 2)
times 510 - ($ - $$) db 0 times 510 - ($ - $$) db 0
dw 0xAA55 dw 0xAA55 ;; Magic number to mark sector as bootable