3afeafc9d4
- basic pointers and reading values from pointers works - writing to pointers not yet implemented (looks painful so a problem for tomorrow) - updated print library. the compiler has this hardcoded in all programs for now
332 lines
6.0 KiB
Plaintext
332 lines
6.0 KiB
Plaintext
// lib:
|
|
// print.dsa
|
|
|
|
// usage:
|
|
//
|
|
// include print "<relative path>""
|
|
//
|
|
// usage for print:
|
|
// push (register containing address of string)
|
|
// push pcx
|
|
// jmp print::print
|
|
//
|
|
// usage for reset:
|
|
// push pcx
|
|
// jmp print::reset
|
|
//
|
|
// usage for clear:
|
|
// push pcx
|
|
// jmp print::clear
|
|
//
|
|
// usage for print_byte:
|
|
// push (register containing byte)
|
|
// push pcx
|
|
// jmp print::print_byte
|
|
//
|
|
// usage for print_word:
|
|
// push (register containing word)
|
|
// push pcx
|
|
// jmp print::print_word
|
|
//
|
|
// usage for print_num:
|
|
// push (register containing number to print in decimal)
|
|
// push pcx
|
|
// jmp print::print_num
|
|
//
|
|
|
|
include maths "../maths/core.dsa"
|
|
|
|
dw display: 0x20000
|
|
dw current: 0x20000
|
|
|
|
// ------------------------------------------
|
|
// prints the string at addr(arg[0]) to the screen. (no trailing whitespace unless explicitly provided)
|
|
print:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw bpr, rg0, 8
|
|
ldw current, rg1
|
|
|
|
_print_loop:
|
|
ldb rg0, acc
|
|
cmp acc, zero
|
|
jeq _end
|
|
stb acc, rg1
|
|
|
|
addi rg0, 1
|
|
addi rg1, 1
|
|
|
|
jmp _print_loop
|
|
|
|
// ------------------------------------------
|
|
println:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw bpr, rg0, 8
|
|
ldw current, rg1
|
|
|
|
_println_loop:
|
|
ldb rg0, acc
|
|
cmp acc, zero
|
|
jeq _println_end
|
|
stb acc, rg1
|
|
|
|
addi rg0, 1
|
|
addi rg1, 1
|
|
|
|
jmp _println_loop
|
|
|
|
_println_end:
|
|
call print_newline
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// prints the value of arg[0] to the screen.
|
|
print_word:
|
|
// initialise
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
// load byte into acc
|
|
ldw bpr, rg0, 8
|
|
ldw current, rg1
|
|
|
|
addi rg1, 3
|
|
|
|
stb rg0, rg1
|
|
subi rg1, 1
|
|
shr rg0, 8
|
|
stb rg0, rg1
|
|
subi rg1, 1
|
|
shr rg0, 8
|
|
stb rg0, rg1
|
|
subi rg1, 1
|
|
shr rg0, 8
|
|
stb rg0, rg1
|
|
|
|
addi rg1, 4
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// prints the last byte of arg[0] to the screen.
|
|
print_byte:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw bpr, rg0, 8
|
|
ldw current, rg1
|
|
|
|
stb rg0, rg1
|
|
addi rg1, 1
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// prints the value of arg[0] to the screen in hex.
|
|
print_hex_word:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw current, rg1
|
|
|
|
ldb bpr, rg0, 8
|
|
push rg0
|
|
call _print_hex_byte
|
|
addi spr, 4
|
|
|
|
ldb bpr, rg0, 9
|
|
push rg0
|
|
call _print_hex_byte
|
|
addi spr, 4
|
|
|
|
ldb bpr, rg0, 10
|
|
push rg0
|
|
call _print_hex_byte
|
|
addi spr, 4
|
|
|
|
ldb bpr, rg0, 11
|
|
push rg0
|
|
call _print_hex_byte
|
|
addi spr, 4
|
|
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// prints the last byte of arg[0] to the screen in hex.
|
|
print_hex_byte:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw bpr, rg0, 8
|
|
ldw current, rg1
|
|
|
|
call _print_hex_byte
|
|
jmp _end
|
|
|
|
// function body
|
|
_print_hex_byte:
|
|
// mask to get lower nibble
|
|
lli 0xF, rg2
|
|
// save rg0 state
|
|
push rg0
|
|
|
|
shr rg0, 4
|
|
and rg0, rg2, rg0
|
|
call _print_hex_nibble
|
|
pop rg0
|
|
|
|
and rg0, rg2, rg0
|
|
call _print_hex_nibble
|
|
return
|
|
|
|
// print a hex digit
|
|
_print_hex_nibble:
|
|
lli 10, rg3
|
|
cmp rg0, rg3
|
|
jlt _print_hex_nibble_number
|
|
addi rg0, 0x37, rg0
|
|
stb rg0, rg1
|
|
addi rg1, 1
|
|
return
|
|
|
|
// helper function.
|
|
_print_hex_nibble_number:
|
|
addi rg0, 0x30, rg0
|
|
stb rg0, rg1
|
|
addi rg1, 1
|
|
return
|
|
|
|
// ------------------------------------------
|
|
// print whitespace
|
|
print_whitespace:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw current, rg1
|
|
lli 0x20, rg0
|
|
stb rg0, rg1
|
|
addi rg1, 1
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// print newline
|
|
print_newline:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
// load variables into registers
|
|
ldw display, rg0
|
|
ldw current, rg1
|
|
|
|
// get the offset from the display base
|
|
sub rg1, rg0, rg0
|
|
|
|
lwi 80, rg2
|
|
pusha 3
|
|
push rg0
|
|
push rg2
|
|
call maths::divmod
|
|
pop zero // result
|
|
pop rg3 // remainder
|
|
popa 3
|
|
|
|
sub rg1, rg3, rg2
|
|
addi rg2, 80, rg1
|
|
|
|
// _end saves the display state
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// prints arg[0] as a decimal number to the screen.
|
|
print_num:
|
|
push bpr
|
|
mov spr, bpr
|
|
|
|
ldw bpr, rg0, 8 // load number to print
|
|
lli 0, rg5 // rg5 = digit counter
|
|
|
|
// check if number is zero
|
|
cmp rg0, zero
|
|
jne _print_num_extract_digits
|
|
|
|
// special case: print '0' for zero
|
|
lli 0x30, rg6
|
|
push rg6 // push digit to stack buffer
|
|
lli 1, rg5 // we have 1 digit
|
|
jmp _print_num_output
|
|
|
|
_print_num_extract_digits:
|
|
// divide by 10 repeatedly to get digits
|
|
cmp rg0, zero
|
|
jeq _print_num_output
|
|
|
|
// call divmod(rg0, 10)
|
|
push rg0 // dividend
|
|
lli 10, rg1
|
|
push rg1 // divisor (10)
|
|
call maths::divmod
|
|
pop rg0 // quotient (continue dividing this)
|
|
pop rg1 // remainder (the digit)
|
|
|
|
// convert digit to ASCII and push to stack buffer
|
|
addi rg1, 0x30, rg6 // convert to ASCII
|
|
push rg6 // push digit to stack
|
|
inc rg5 // increment digit counter
|
|
|
|
jmp _print_num_extract_digits
|
|
|
|
_print_num_output:
|
|
// now print digits (pop them off in reverse order)
|
|
ldw current, rg1 // get display pointer
|
|
|
|
_print_num_output_loop:
|
|
// check if we've printed all digits
|
|
cmp rg5, zero
|
|
jeq _print_num_done
|
|
|
|
// pop digit and print it
|
|
pop rg6
|
|
stb rg6, rg1
|
|
addi rg1, 1
|
|
dec rg5
|
|
|
|
jmp _print_num_output_loop
|
|
|
|
_print_num_done:
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// resets the cursor position on the screen to 0x20000. (0,0)
|
|
reset:
|
|
push bpr
|
|
mov spr, bpr
|
|
ldw display, rg1
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// clears the screen
|
|
clear:
|
|
push bpr
|
|
mov spr, bpr
|
|
// display size = 2000 bytes / 500 words
|
|
lli 500 rg0
|
|
ldw display, rg1
|
|
|
|
_clear_loop:
|
|
dec rg0
|
|
stw zero, rg1
|
|
addi rg1, 4
|
|
cmp rg0, zero
|
|
jgt _clear_loop
|
|
jmp _end
|
|
|
|
// ------------------------------------------
|
|
// return
|
|
_end:
|
|
stw rg1, current
|
|
|
|
mov bpr, spr
|
|
pop bpr
|
|
return
|