Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Create a simple integer calculator. You may either use Microsoft Visual Studio o

ID: 3872787 • Letter: C

Question

Create a simple integer calculator.

You may either use Microsoft Visual Studio or the DOS command prompt window to assemble, link and execute the program. You need to submit a ZIP file that contains the assembly language source code (.ASM), the executable program (.EXE), and sample output from running the program. Optionally any other documentation you wish to provide that explains the program or problems you encountered.

The program should execute as follows:

Enter first number or 0 to exit:

Enter second number:

Enter operation: (+, -, *, /):

The answer is:

Loop to allow the user to perform another calculation.

You may use the functions ReadInt, ReadChar, WriteInt, WriteString, WriteHex and any other functions you find useful from Irvine32.lib. You do not need to use them if you prefer to write your own routines. The Irvine functions are documented in chapter 5.

A program that performs only the plus (+) and minus (-) functions successfully with be graded with a B. In order to be graded as an A, the program should also support the multiply (*) and divide (/) operations and display the quotient and remainder of the / (divide) operation, and display the answers in both decimal and hexadecimal.

Explanation / Answer


           .data
openMsg:   .asciiz "Welcome to SPIM Calculator 1.0!"
newLine:   .asciiz " "            # line return
firstArg:   .asciiz " Enter the first number:"
secondArg:   .asciiz "Enter the second number:"
operator:   .asciiz "Enter the operation (+,-,*,/), then press enter key: "
anotherCalc:.asciiz " Another Calculation (y/n)? "
exitMsg:   .asciiz " Calculator Terminated. "

spaceC:    .asciiz " "   
invOpMsg:   .asciiz "Invalid Operator!"
eqOp:       .asciiz " = "
oParen:       .asciiz " ("
cParen:       .asciiz ")"

a0_op:           .word 0            # address/space to hold an integer input
a1_op:           .word 0            # address/space to hold an integer input
operation:       .space 16            # address/space to hold the operator input
loopingBool:   .space 16            # address/space to hold whether to preform another calculation

           .text
           .globl main  
# OPERATION BRANCHES (not subroutines, are the intermediary steps if a subroutine is required, and contains the whole operation if not)          
addOp:       add $s0, $a0, $a1        # add the aruments stored in $a0 and $a1
           j print                   # return to main to print solved function
subOp:       sub $s0, $a0, $a1       # subtract the aruments stored in $a0 and $a1
           j print                   # return to main to print solved function
multi:       jal multiply           # call the subroutine multiply
           j print                   # return to main
divi:       jal divide               # call the subroutine divide
           j print                   # return to main to print solved function
divPrint:   li $v0, 4               # syscall 4 (print_str)
           la $a0, oParen           # open parenthesis
           syscall  
           li $v0, 1               # syscall 1 (print_int)
           move $a0, $s1           # print the remainder of the division loop
           syscall      
           li $v0, 4               # syscall 4 (print_str)
           la $a0, cParen           # close parenthesis
           syscall
           j query                   # continue on to after the function is normally printed
          
# MULTIPLY SUBROUTINE (assumes arguments are stored in $a0 and $a1)
multiply:   sub $sp, $sp, 4         # make room for $t0
           sw $t0, 0($sp)          # save $t0 to the stack
           add $t0, $zero, $zero   # start, $t0 = 0
          
multLoop:    beq $a1, $zero, multEol # loop on $a1
           add $t0, $t0, $a0       # add another to $a0
           sub $a1, $a1, 1         # $a1 is a counter
           j multLoop          
          
multEol:  
           move $s0, $t0           # save the result in repository $s0
           lw $t0, 0($sp)         # restore $t0
           add $sp, $sp, 4           # restore the stack
           jr $ra                   # return to caller
      
# DIVIDE SUBROUTINE (assumes argumetnts are stored in $a0 and $a1)
divide:       sub $sp, $sp, 8           # make room for $t0
           sw $t0, 0($sp)           # save $t0 to the stack
           sw $t1, 4($sp)           # save $t1 to the stack
           add $t0, $zero, $a0       # start, $t0 = $a0 (will hold the remainder)
           add $t1, $zero, $zero   # start, set counter $t1 = 0
divLoop:   bgt   $a1, $t0, divEol   # loop while $t0 is still greater or equal to the divisor ($a1)
           sub $t0, $t0, $a1       # subtract one level of divisor from whats left in $t0
           add $t1, $t1, 1           # increment the counter ($t1++)
           j divLoop
divEol:       move $s0, $t1           # store the quotent in repository $s0
           move $s1, $t0           # store the remainder in repository $s1
           lw $t0, 0($sp)           # restore $t0
           lw $t1, 4($sp)           # restore $t1
           add $sp, $sp, 8           # restore the stack
           jr $ra                   # return to caller
          
# BEGIN MAIN FUNCTION          
main:       li $v0, 4              # syscall 4 (print_str)
           la $a0, openMsg        # print the opening string
           syscall               

           la $a0, newLine        # print a new line
           syscall               
          
loop:       li $v0, 4               # syscall 4 (print_str)
           la   $a0, firstArg         # prompt for the first integer argument
           syscall
          
           li $v0, 5                # syscall 5 (read_int)
           syscall
           sw $v0, a0_op             # load to $a0 the address to hold the read operator
          
           li $v0, 4                 # syscall 4 (print_str)
           la $a0, secondArg         # prompt for the second integer argument
           syscall
          
           li $v0, 5               # syscall 5 (read_int)
           syscall
           sw $v0, a1_op             # load to $a0 the address to hold the read operator
          
           li $v0, 4                # syscall 4 (print_str)
           la $a0, operator         # query for which operator to use
           syscall
          
           addi $v0, $zero, 8     # syscall 8 (read_str)
           la $a0, operation     # store the operation to use within a word
           li $a1, 16               # allocate size for the operation string
           syscall
          
           #remove the linefeed from the operator string in oder to just deal with the ascii number of the operator (and makes printing easier)
           li $s0,0               # Set index to 0
remove:       lb $a3,operation($s0)   # Load character at index
           addi $s0,$s0,1         # Increment index
           bnez $a3,remove        # Loop until the end of string is reached
           beq $a1,$s0,skip       # Do not remove when string = maxlength
           sub $s0,$s0,2            # If above not true, Backtrack index to
           sb $0, operation($s0)   # Add the terminating character in its place
          
skip:       la $a0, operation       # load the inputted operation into repository $a0
           li $s0, 43               # store the numerical representation for the string + in repository $s0
           li $s1, 45               # store the numerical representation for the string - in repository $s1
           li $s2, 42               # store the numerical representation for the string * in repository $s2
           li $s3, 47               # store the numerical representation for the string / in repository $s3
           lw $s4, 0($a0)           # store the inputted operator in repository $s4
           lw $a0, a0_op           # load in the first argument integer into $a0
           lw $a1, a1_op           # load in the second argument integer into $a1
           beq $s0, $s4, addOp       # if the operator is +, branch to addOp and then to cont
           beq $s1, $s4, subOp       # if the operator is -, branch to subOp and then to cont
           beq   $s2, $s4, multi    # if the operator is *, run the multiply subroutine and branch to cont
           beq $s3, $s4, divi       # if the operator is /, run the divide subroutine and branch to cont
          
           li $v0, 4               # syscall 4 (print_str)
           la $a0, invOpMsg       # display error message for any string that is not an operator
           syscall
           j query                   # skip printing formula and go directly to asking for another calculation
                      
print:       #the following is to print the result in equation form
           li $v0, 1               # syscall 1 (print_int)
           lw $a0, a0_op           # print the first argument
           syscall
          
           li $v0, 4               # syscall 4 (print_str)
           la $a0, spaceC           # add a space
           syscall
           la $a0, operation       # print the operation
           syscall
           la $a0, spaceC           # add a space
           syscall
          
           li $v0, 1               # syscall 1 (print_int)
           lw $a0, a1_op           # print the second argument
           syscall
          
           li $v0, 4               # syscall 4 (print_str)
           la $a0, eqOp           # print out the symbol = for the equation
           syscall
          
           li $v0, 1               # syscall 1 (print_int)
           move $a0, $s0           # print the result of the calculation
           syscall
          
           beq $s3, $s4, divPrint   # handles division print case where remainder must be printed as well
          
query:       li $v0, 4              # syscall 4 (print_str)
           la $a0, anotherCalc    # query whether to do another calculation
           syscall
          
           addi $v0, $zero, 8        # syscall 8 (read_str)
           la $a0, loopingBool    # store the query for whether to continue looping
           li $a1, 16               # allocate space for the string input
           syscall
          
           li $s0, 2670              # load string ascii value for 'n', which is 2670 (neither are the ascii values, they just have linefeeds on the end so they're values are off)
           li $s1, 2681           # load string ascii value for 'y', which is 2681
           lw $s2, 0($a0)            # load result of whether to continue looping or not, and will branch when $t1 is equal to $t2
           beq $s0, $s2, exit        # break the loop if the statement evaluates to true
           beq $s1, $s2, loop       # continue looping if answer is yes
exit:
          
           li $v0, 4               # syscall 4 (print_str)
           la $a0, exitMsg        # string is a line return (ALMOST END OF PROGRAM)
           syscall
          
           li $v0, 10              # syscall 10 (exit the program)
           syscall

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote