; print.asm ; Some simple SplitBit subroutines for printing. ; Anachronaut ; 10/27/2024 #Program BRI start ; Branch immediately to the start of the program. lineFeed: INIA 0x0A ; Load the character for linefeed into A. OUTA 0x00 ; Output it. RET ; Return to the caller. blankSpace: INIB 0x20 ; Set B to the ASCII value for space. OUTB 0x00 ; Print it. RET ; Expects A to contain the number of spaces to print. blankSpaces: INIB 0x20 ; Set B to the ASCII value for space. OUTB 0x00 ; Print it. BRA printDone ; If A is zero, we're done. DECA ; Decrement A. BRI blankSpace ; Branch back to the loop again. printString: ; Expects Data Pointer to be set to the beginning of the string to be printed. LDA ; Move the first character of the string into A. BRA printDone ; If A is NULL, the string is finished, so return. OUTA 0x00 ; Output the character. INCD ; Increment Data Pointer to the next character. BRI printString ; Branch to the beginning of the loop. printDone: RET ; Return to the caller. ; Expects A to contain the value to be printed in decimal form. printByteDecimal: ; Clear the buffer we're going to write into. SETD DecimalValue ; Set the Data Pointer to the buffer. RSTB ; Set B to 0. STB ; Store it in the buffer. INCD ; Increment to the tens place. STB ; Store 0 in it. INCD ; Increment to the hundred's place. STB ; Store 0 in it. INIB 0d10 ; Load 10 into B. PSHA ; Save the value onto the stack. printDecimalLoopStart: POPA ; Pop the value to A from the stack. CCF ; Clear the Carry Flag. SUB ; Subtract 10 from the value in A. BRC getOnes ; If 10 is bigger than A, We're done looping and A contains the ones. BRA getOnes ; If the value 0, we're also done. ; Otherwise, increment the tens place. SETD DecimalValue ; Set the Data Pointer to the buffer. INCD ; Increment to the tens place. PSHQ ; Save the new value onto the stack. LDA ; Load the number of tens into A. INCA ; Increment it. ; Now check to see if there are ten tens and we need to carry to the hundreds. CCF ; Clear the Carry Flag. SUB ; Subtract 10 from A. BRQ incrementHundreds ; If Q is 0, set the tens to 0 and increment the hundreds place. STA ; Otherwise, store the value back to the tens place. BRI printDecimalLoopStart ; and loop again. incrementHundreds: STQ ; Store 0 in the tens place. INCD ; Increment the Data Pointer to the hundreds place. LDA ; Load it into A. INCA ; Increment it. STA ; Store it back again. BRI printDecimalLoopStart ; and Loop again. getOnes: SETD DecimalValue ; Set the Data Pointer to the ones place. STA ; Store A in it. ; At this point we're done. We just need to print the digits with the printDecimalDigit subroutine. INCD INCD ; Increment the Data Pointer twice to the hundreds place. decimalCheckLoop: LDA ; Load the value into A. BRA checkTens ; If the hundreds are 0, skip printing their digit. CALL printDecimalDigit ; Otherwise, print it. DECD LDA CALL printDecimalDigit ; And the tens place, too. BRI printOnes ; And finally, the ones. checkTens: DECD ; Decrement to the tens place. LDA ; Load it into A. BRA printOnes ; If the tens are zero, skip printing their digit, too. CALL printDecimalDigit ; Otherwise, print it. printOnes: DECD ; Decrement to the ones place. LDA CALL printDecimalDigit ; Print it no matter what. RET ; We're done, return to the caller. ; Expects A to contain the byte you want to print as a hexadecimal value. printByteHex: INIB 0x00 ; Set B to 0. SHR SHR SHR SHR ; Shift Right four times to move the high nybble into the lower half of A. CALL printHexDigit ; Print the nybble. INIA 0x00 ; Set A to 0. SHL SHL SHL SHL ; Shift left four times to move the low nybble back into the lower half of A. CALL printHexDigit ; Print the nybble. RET ; Return to the caller. ; Expects A to contain the nybble you want to print. printHexDigit: INIB 0d10 ; Set B to 10. SUB ; Subtract it. BRC printDecimalDigit ; If the Carry Flag is set, the digit is less than 9. Print it. ; Since it's greater than 9, add the ASCII offset for capital letters. INIB 0x37 ; Set B to the offset. ADD ; Add it to A. OUTQ 0x00 ; Print the result. RET ; Return to the caller. ; Expects A to contain a single BCD digit to print. printDecimalDigit: INIB 0x30 ; Load ASCII offset for numbers into B. CCF ; Clear the Carry Flag. ADD ; Add it to A. OUTQ 0x00 ; Send it to the output. RET ; Return from subroutine. #Data ; This is where printDecimal stores its result. DecimalValue: 0x00 ; The ones place. 0x00 ; The tens place. 0x00 ; The hundreds place. 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00