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

Create modular code and interface with unfamiliar modularized code The Task In t

ID: 3940472 • Letter: C

Question

Create modular code and interface with unfamiliar modularized code The Task In this project you will be combining and building on what you have done in the first 2 projects. You are free to reuse any code that you wrote in the previous 2 projects or the provided Project 2 solution. This program should be a full calculator that uses the UART for both input and output. Calculator Operation You calculator should accept full mathematical expressions with 2 numbers and an operator (e.g. “1+2=”) and print the result to the UART using the provided module. It should handle the operators to add (+), subtract (-), and multiply (*), but it does not need to handle division. It should accept multiple expressions and generate the appropriate outputs for each expression without manually resetting the simulation (e.g. the input “51-4=6*2=” should output “47” followed by “12”). UART Module The UART Module is available on Blackboard as an ASM file. You can import it into a PLP project by navigating to “Project”, selecting “Import ASM file”, and then selecting the UART Module ASM file. The module contains a print function, project_3_output_number, which uses 2 registers as input arguments, $a0 and $a1. The register, $a0, is the value to be displayed on the UART and register $a1 is used to indicate the error message. If $a1 is non-zero an error message will be displayed regardless of the value in $a0. The table below indicates the mapping between $a1 and the UART output. $a0 $a1 UART Output Signed Number 0 Signed Decimal Number Any Value 1 “Error: Invalid character ” Any Value 2 “Error: Invalid expression ” Any Value 3 “Error: Input overflow ” Any Value 4 “Error: Output overflow ” Any Value 5 “Error: Unknown error code ” The only error your program needs to check for is invalid character ($a1 = 1), which is when a character is not a number character or one of the 3 operators (you can also allow space characters, but this is not required). If an invalid character is found the rest of the expression, up to the ‘=’ character, must still be read from the UART so that it does not affect the next expression. You may assume input follows the following format: '=' If at any point the contains something other than a character from '0' through '9' then the expression has an invalid character. In order to use the output function you PLP program needs to have initialized the stack pointer ($sp). You should typically initialize the stack pointer to 0x10fffffc (the last address of RAM). The output is called using the following instruction (the line following this instruction must be a valid PLP instruction otherwise you will most likely get an error during simulation): call project3_output_number After this function call, the value in $a0 (unless $a1 is set to something other than 0) will be displayed on the UART and then the program will return to the instruction immediately following the call instruction.

Explanation / Answer


bcd_storage_p3:
   .space 10   #creates 10 words here

invalid_char_p3:
   .asciiz "ERROR: Invalid character "
invalid_expression_p3:
   .asciiz "ERROR: Invalid expression "
input_overflow_p3:
   .asciiz "ERROR: Input overflow "
output_overflow_p3:
   .asciiz "ERROR: Output overflow "
unknown_error_p3:
   .asciiz "ERROR: Unknown error code "


project3_output_number:
push $ra
# Check for error
beq $a1, $0, UART_no_error_p3
   nop
   addiu $t0, $0, 1
   li $a0, invalid_char_p3
   beq $a1, $t0, display_error_message_p3
   nop
   addiu $t0, $t0, 1
   li $a0, invalid_expression_p3
   beq $a1, $t0, display_error_message_p3
   nop
   addiu $t0, $t0, 1
   li $a0, input_overflow_p3
   beq $a1, $t0, display_error_message_p3
   nop
   addiu $t0, $t0, 1
   li $a0, output_overflow_p3
   beq $a1, $t0, display_error_message_p3
   nop
   li $a0, unknown_error_p3

display_error_message_p3:
   jal libplp_uart_write_string_p3
   nop
   pop $ra
   return


UART_no_error_p3:

#INITIALIZATIONS
# Saved Values
lui $s0, 0xF000   #UART
li $s1, 0x1   #mask for bit 0, used by put_char
li $s2, 0x2   #mask for bit 1, used by get_char
li $s3, 10       #used by decimal_to_binary
li $s4, 48       #subtract from ascii for decimal, used by decimal_to_binary

# Temporary Values
li $t0, 0       #counter in subroutines
li $t1, 0       #x: used for UART character reads and writes

# check if 0
bne $a0, $0, non-zero_input_p3
   nop
   addiu $t1, $0, '0'   # set UART output value to '0'
   jal put_char_p3
   nop
   addiu $t1, $0, 10   # set UART output value to ' '
   jal put_char_p3
   nop
   pop $ra
   return
non-zero_input_p3:

# Get sign bit
move $t2, $a0
srl $t2, $t2, 31
beq $t2, $0, non_negative_output_p3
   nop
   jal handle_negative_p3
   nop
non_negative_output_p3:
jal to_bcd_p3
nop
jal display_bcd_p3
nop
pop $ra
return

#=======================================FUNCTIONS=======================================

#Description: places number result ($s7) into the space at the label bcd_storage
#Resources: #uses $t0, t2, $t3, $t4
to_bcd_p3:
push $ra
li $s5, bcd_storage_p3
#set 10's place followed call subtract function to store bcd
li $s6, 1000000000   #10
jal base10_subtract
nop
li $s6, 100000000    #9
jal base10_subtract
nop
li $s6, 10000000   #8
jal base10_subtract
nop
li $s6, 1000000   #7
jal base10_subtract
nop
li $s6, 100000   #6
jal base10_subtract
nop
li $s6, 10000   #5
jal base10_subtract
nop
li $s6, 1000   #4
jal base10_subtract
nop
li $s6, 100   #3
jal base10_subtract
nop
li $s6, 10       #2
jal base10_subtract
nop
li $s6, 1       #1
jal base10_subtract
nop
pop $ra
jr $ra
nop


#Description: repeats $s7 - $s6 as many times as possilbe, where s6 is a multiple of 10
#Resources: #uses $t0, t2, $t3, $t4
base10_subtract:
li $t5, 0       # bcd place value
sltu $t6, $a0, $s6   # determine if number less than decimal place
   subtract_loop_p3:
       bne $t6, $0, exit_sub_loop_p3
       nop
       subu $a0, $a0, $s6
       addiu $t5, $t5, 1   #incriment bcd
       sltu $t6, $a0, $s6   # determine if number less than decimal place
       j subtract_loop_p3
       nop
exit_sub_loop_p3:
sw $t5, 0($s5)   # store bcd value
addiu $s5, $s5, 4   # increment BCD pointer to next word
jr $ra
nop

#Description: places number result ($s7) into the space at the label bcd_storage
#Resources: #uses $t0, t2, $t3, $t4
display_bcd_p3:
   push $ra
   li $t3, bcd_storage_p3
   li $t2, 10       #count down for prints
   # for 10 starting at bcd_storage, add 48 and put char
   lw $t1, 0($t3)
   remove_preceeding_zeros_p3:
       bne $t1, $0, display_bcd_loop_p3   # branch if non-zero
       nop
       addiu $t3, $t3, 4   # increment BCD pointer  
       subu $t2, $t2, $s1   # decrement $t2
       lw $t1, 0($t3)
       j remove_preceeding_zeros_p3
       nop
   display_bcd_loop_p3:
       # convert to ascii and print
       addu $t1, $t1, $s4
       jal put_char_p3
       nop
       addiu $t3, $t3, 4   # increment BCD pointer
       subu $t2, $t2, $s1   # decrement $t2
       lw $t1, 0($t3)
       bne $t2, $0, display_bcd_loop_p3
       nop
   addiu $t1, $0, 10   # set UART output value to ' '
   jal put_char_p3
   nop
   pop $ra
   jr $ra
   nop


#Description: outputs negative sign and converts from 2's compliment  
#   Resources: $s0 = UART, $s1 = 1, $a0 = number to convert, $t1 = character to print
handle_negative_p3:
push $ra       # save return address
addiu $t1, $0, '-'   # set UART output value to '-'
jal put_char_p3
nop
pop $ra       # restore return address

# 2's compliment conversion
nor $a0, $a0, $a0
addu $a0, $a0, $s1
jr $ra
nop


#Description: Writes $t1 to UART
#Resources: $s0 = UART, $s1 = 1, $t0 = temp
put_char_p3:
   lw $t0, 4($s0)   # load status register
   and $t0, $t0, $s1   # mask for clear to send
   bne $t0, $s1, put_char_p3
   nop
   sw $t1, 12($s0)   # store in send buffer
   sw $s1, 0($s0)   # command register: send
   jr $ra
   nop


# From PLP UART Library

libplp_uart_write_p3:
   lui $t0, 0xf000       #uart base address
libplp_uart_write_loop_p3:
   lw $t1, 4($t0)       #get the uart status
   andi $t1, $t1, 0x01   #mask for the cts bit
   beq $t1, $zero, libplp_uart_write_loop_p3
   nop
   sw $a0, 12($t0)   #write the data to the output buffer
   sw $t1, 0($t0)       #send the data!
   jr $31
   nop

libplp_uart_write_string_p3:        #we have a pointer to the string in a0, just loop and increment until we see a
   move $t9, $31       #save the return address
   move $t8, $a0       #save the argument
libplp_uart_write_string_multi_word_p3:
   lw $a0, 0($t8)       #first 1-4 characters
   ori $t0, $zero, 0x00ff #reverse the word to make it big endian
   and $t1, $t0, $a0   #least significant byte
   sll $t1, $t1, 24
   srl $a0, $a0, 8
   and $t2, $t0, $a0   #second byte
   sll $t2, $t2, 16
   srl $a0, $a0, 8
   and $t3, $t0, $a0   #third byte
   sll $t3, $t3, 8
   srl $a0, $a0, 8       #last byte in a0
   or $a0, $t1, $a0
   or $a0, $t2, $a0
   or $a0, $t3, $a0
   beq $a0, $zero, libplp_uart_write_string_done_p3
   nop
   ori $t7, $zero, 4
libplp_uart_write_string_loop_p3:
   jal libplp_uart_write_p3   #write this byte
   addiu $t7, $t7, -1
   srl $a0, $a0, 8
   bne $a0, $zero, libplp_uart_write_string_loop_p3
   nop
   beq $t7, $zero, libplp_uart_write_string_multi_word_p3
   addiu $t8, $t8, 4   #increment for the next word
libplp_uart_write_string_done_p3:
   jr $t9           #go home
   nop

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