// lib: // print.dsa // usage: // // include print """ // // 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