.ORIG x3000 JUMP MAIN ; ------------------------------------------------------ ; Main Function ; Register Assignments: ; R5 - Return Value ; R6 - Stack Pointer ; R7 - Return Address ASCII_172 .STRINGZ "172" ASCII_9 .STRINGZ "9" ASCII_M43 .STRINGZ "-43" ASCII_M17 .STRINGZ "-17" MAIN ;; + 172 LD R0, TOTAL LEA R1, BUF LD R2, BUFSIZE JSR ITOA LEA R0, BUF TRAP x22 ; PUTS LEA R1, ASCII_172 LEA R0, BUF JSR STRCPY JSR ATOI LD R0, TOTAL ADD R0, R0, R1 ST R0, TOTAL LD R0, ASCII_PLUS TRAP x21 ; PUTC LEA R0, BUF TRAP x22 ; PUTS LD R0, ASCII_NL TRAP x21 ; PUTC ;; * 9 LD R0, TOTAL LEA R1, BUF LD R2, BUFSIZE JSR ITOA LEA R0, BUF TRAP x22 ; PUTS LEA R1, ASCII_9 LEA R0, BUF JSR STRCPY JSR ATOI LD R0, TOTAL MUL R0, R0, R1 ST R0, TOTAL LD R0, ASCII_STAR TRAP x21 ; PUTC LEA R0, BUF TRAP x22 ; PUTS LD R0, ASCII_NL TRAP x21 ; PUTC ;; - -43 LD R0, TOTAL LEA R1, BUF LD R2, BUFSIZE JSR ITOA LEA R0, BUF TRAP x22 ; PUTS LEA R1, ASCII_M43 LEA R0, BUF JSR STRCPY JSR ATOI LD R0, TOTAL SUB R0, R0, R1 ST R0, TOTAL LD R0, ASCII_MINUS TRAP x21 ; PUTC LEA R0, BUF TRAP x22 ; PUTS LD R0, ASCII_NL TRAP x21 ; PUTC ;; / -17 LD R0, TOTAL LEA R1, BUF LD R2, BUFSIZE JSR ITOA LEA R0, BUF TRAP x22 ; PUTS LEA R1, ASCII_M17 LEA R0, BUF JSR STRCPY JSR ATOI LD R0, TOTAL JSR DIV ST R2, TOTAL LD R0, ASCII_SLASH TRAP x21 ; PUTC LEA R0, BUF TRAP x22 ; PUTS LD R0, ASCII_NL TRAP x21 ; PUTC ;; Final answer LD R0, TOTAL LEA R1, BUF LD R2, BUFSIZE JSR ITOA LEA R0, BUF TRAP x22 ; PUTS HALT PROMPT .STRINGZ "calc:" BYE .STRINGZ "bye!" ERROR .STRINGZ "error!" BUF .BLKW #16 BUFSIZE .FILL #16 TOTAL .FILL x0000 ASCII_SPACE .FILL x0020 ASCII_STAR .FILL x002A ASCII_PLUS .FILL x002B ASCII_MINUS .FILL x002D ASCII_SLASH .FILL x002F ASCII_0 .FILL x0030 ASCII_NL .FILL x000A ;;; DIV (divide) - divide one integer by another ;;; Inputs: R0 - dividend ;;; R1 - divisor ;;; Outputs: R2 - quotient ;;; R3 - remainder DIV INC R6, #-1 STR R4, R6, #0 BRnp R1, DIV_NOTBYZERO AND R1, R0, R0 LEA R0, ERROR TRAP x22 ; PUTS AND R0, R1, R1 CONST R1, #0 JUMP DIV_DONE DIV_NOTBYZERO CONST R2, #0 AND R3, R0, R0 BRn R0, DIV_N DIV_P BRn R1, DIV_PN ; Positive dividend DIV_PP ; Divide positive by positive SUB R4, R3, R1 BRn R4, DIV_DONE INC R2, #1 SUB R3, R3, R1 JUMP DIV_PP DIV_PN ; Divide positive by negative ADD R4, R3, R1 BRn R4, DIV_DONE INC R2, #-1 ADD R3, R3, R1 JUMP DIV_PN DIV_N ; Negative dividend BRn R1, DIV_NN DIV_NP ; Divide negative by positive ADD R4, R3, R1 BRp R4, DIV_DONE INC R2, #-1 ADD R3, R3, R1 JUMP DIV_NP DIV_NN ; Divide negative by negative SUB R4, R3, R1 BRp R4, DIV_DONE INC R2, #1 SUB R3, R3, R1 JUMP DIV_NN DIV_DONE LDR R4, R6, #0 INC R6, #1 JUMPR R7 ;;; ATOI (ascii to integer) - converts well-formed integer string to integer ;;; Inputs: R0 - pointer to null terminated string ;;; Outputs: R1 - integer ATOI INC R6, #-5 STR R0, R6, #0 STR R2, R6, #1 STR R3, R6, #2 STR R4, R6, #3 STR R7, R6, #4 CONST R1, #0 ; Initialize return value to 0 LDR R4, R0, #0 LD R3, ASCII_MINUS SUB R4, R4, R3 ; R4 will be zero if number is negative BRnp R4, ATOI_LOOP INC R0, #1 ATOI_LOOP LDR R2, R0, #0 BRz R2, ATOI_LOOP_DONE CONST R3, #10 MUL R1, R1, R3 ; Found another digit, multiply return value by 10 LD R3, ASCII_0 SUB R3, R2, R3 ADD R1, R1, R3 ; Add new digit INC R0, #1 JUMP ATOI_LOOP ATOI_LOOP_DONE BRnp R4, ATOI_DONE ; If there was a minus sign, negate the number NOT R1, R1 INC R1, #1 ATOI_DONE LDR R7, R6, #4 LDR R4, R6, #3 LDR R3, R6, #2 LDR R2, R6, #1 LDR R0, R6, #0 INC R6, #5 JUMPR R7 ;;; ITOA (integer to ascii) - converts well-formed integer string to integer ;;; Inputs: R0 - integer ;;; R1 - pointer to null terminated string ;;; R2 - length of string ITOA INC R6, #-7 STR R0, R6, #0 STR R1, R6, #1 STR R2, R6, #2 STR R3, R6, #3 STR R4, R6, #4 STR R5, R6, #5 STR R7, R6, #6 CONST R5, #0 ; First, calculate output string length CONST R1, #10 BRzp R0, ITOA_LENGTH_LOOP INC R5, #1 ; length++ for the minus sign ITOA_LENGTH_LOOP INC R5, #1 JSR DIV AND R0, R2, R2 BRnp R2, ITOA_LENGTH_LOOP LDR R2, R6, #2 ; Check for buffer overflow SUB R7, R2, R5 INC R7, #-1 BRn R7, ITOA_DONE LDR R0, R6, #0 LDR R4, R6, #1 BRzp R0, ITOA_LOOP_HEADER LD R7, ASCII_MINUS ; Write the minus sign STR R7, R4, #0 NOT R0, R0 ; Negate the number INC R0, #1 ITOA_LOOP_HEADER CONST R1, #10 ADD R4, R4, R5 ; Write the number right-to-left (it's easier) CONST R7, #0 STR R7, R4, #0 ; Write the null terminator ITOA_LOOP JSR DIV LD R7, ASCII_0 ADD R7, R3, R7 ; Write remainder INC R4, #-1 STR R7, R4, #0 AND R0, R2, R2 ; Copy quotient to dividend BRp R0, ITOA_LOOP ITOA_DONE LDR R7, R6, #6 LDR R5, R6, #5 LDR R4, R6, #4 LDR R3, R6, #3 LDR R2, R6, #2 LDR R1, R6, #1 LDR R1, R6, #0 INC R6, #7 JUMPR R7 ;;; STRCPY (string copy) - length-unchecked copy of null terminated string to buffer ;;; Inputs: R0 - pointer to buffer ;;; R1 - pointer to null terminated string ;;; Outputs: none STRCPY INC R6, #-3 STR R0, R6, 0 STR R1, R6, 1 STR R2, R6, 2 STRCPY_LOOP LDR R2, R1, 0 STR R2, R0, 0 BRz R2, STRCPY_DONE INC R1, #1 INC R0, #1 JUMP STRCPY_LOOP STRCPY_DONE LDR R2, R6, 2 LDR R1, R6, 1 LDR R0, R6, 0 JUMPR R7