            ; Initializes the terminal for input and output.
            ; Subroutine changes R0 and R3
ttyStart    MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            MOV R0, #0x50         ; enable DBGU receipt and transmission
            STR R0, [R3, #0x0]
            MOV PC, LR

            ; Reads and returns a nonnegitave base-10 integer typed by the user.
            ; Continues reading digits until user enters a non-digit character.
            ; The terminating non-digit character is consumed from the input.
            ; Program should have already called ttyStart previously.
            ; Result is placed in R0; subroutine changes R1, R2, and R3.
getInt      MOV R1, LR
            MOV R2, #0             ; R2 accumulates integer typed
            B getInt_get           ; go to retrieving first character
getInt_loop ADD R2, R2, R2, LSL #2 ; R2 = 10 * R2 + digit in R0
            ADD R2, R0, R2, LSL #1
getInt_get  BL getChar             ; retrieve character, repeat if is digit
            SUB R0, R0, #'0'
            CMP R0, #10
            BLO getInt_loop
            MOV R0, R2
            MOV PC, R1
            
            ; Reads a single character from the user. Program
            ; should have already called ttyStart previously.
            ; Result is placed in R0; subroutine changes R3.
getChar     MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            LDR R0, [R3, #0x14]   ; wait until DBGU has received character
            TST R0, #0x1
            BEQ getChar
            LDR R0, [R3, #0x18]   ; now accept it from DBGU
            MOV PC, LR

            ; Displays a NUL-terminated string.
            ; Argument (address of string's first character) is found in R0;
            ; subroutine changes R0, R1, R2, R3, and R12
printStr    MOV R12, LR            ; save LR in R3, since BL changes LR
            MOV R2, R0            ; R2 holds address of current char
printStr_next  LDRB R0, [R2], #1  ; load str[i] into R0, increment R2
            CMP R0, #0            ; if it is '\0', return
            MOVEQ PC, R12
            BL printChar          ; display str[i]
            B printStr_next

            ; Displays a single integer value in base 10. Program
            ; should have already called ttyStart previously.
            ; Argument is found in R0;
            ; subroutine changes R0, R1, R2, R3, and R12
printInt    CMP R0, #0
            BGE printInt_0
            RSB R2, R0, #0        ; R0 is negative - print '-' and negate
            MOV R0, #'-'
            MOV R12, LR
            BL printChar
            MOV LR, R12
            MOV R0, R2

printInt_0  ADD R2, PC, #printInt_data ; load digits into array
            MOV R3, #0x19000000        ;   starting with 1's digit
            ORR R3, R3, #0x990000
            ORR R3, R3, #0x9900
            ORR R3, R3, #0x9A
printInt_1  UMULL R12, R1, R0, R3
            ADD R12, R1, R1, LSL #2
            SUB R12, R0, R12, LSL #1
            ADD R12, R12, #'0'
            STRB R12, [R2], #1
            MOVS R0, R1
            BGT printInt_1

            MOV R12, LR                ; go through array in reverse
printInt_2  LDRB R0, [R2, #-1]!        ;   displaying digits
            BL printChar
            ADD R0, PC, #printInt_data
            CMP R2, R0
            BGT printInt_2

            MOV PC, R12

printInt_data % 10  ; reserve 10 bytes for number's digits

            ; Display a single character. Program should have already
            ; called ttyStart previously.
            ; Argument is found in R0; subroutine changes R1 and R3
printChar   MOV R3, #0xF2000000   ; load DBGU base address 0xFFFFF200 into R3
            MOV R3, R3, ASR #16
            LDR R1, [R3, #0x14]   ; wait until DBGU ready to transmit
            TST R1, #0x2
            BEQ printChar
            STR R0, [R3, #0x1C]   ; send character for DBGU transmission
            MOV PC, LR
