Question: Write a PLP Assembly program that receives a string of characters via the UART, checks if this string is a palindrome, and then uses a
Write a PLP Assembly program that receives a string of characters via the UART, checks if this string is a palindrome, and then uses a print function to print either Yes or No.
A palindrome sequence of characters (typically a word or phrase) that is the same both forwards and backwards. For this, strings will be terminated using a period (.). Assume a string will contain at least one character in addition to a period. You will not need to handle empty strings or strings with only a period. The program should be able to handle multiple strings sent one after another or concatenated together. For example, the string: abba. data. should print Yes followed by No on the next line. Spaces should be ignored when checking for a palindrome and the palindrome should not be case sensitive. For example, A nut for a jar of Tuna. would be considered a palindrome.
When called, depending on the value in register $a0, the following string will be displayed on the simulated UART devices output : call project3_print If $a0 contains a zero then No will be displayed and if $a0 contains a non-zero value (e.g. one) then Yes will be displayed.
To use the print function, the PLP program needs to initialize the stack pointer ($sp) before performing the function call (or any other operations involving the stack pointer). For this reason, the skeleton project file includes an initialization that sets the stack pointer to 0x10fffffc (the last address of RAM).
A skeleton PLP project code is available below. ________________________________________________________________
2 Source Files provided:
.org 0x10000000
# Initializations
li $sp, 0x10fffffc
# Initialize any registers you will be using here.
main:
# TODO: write your primary program within this loop
j main
nop
________________________________________________________________
li $a0, control_message_p3
jal libplp_uart_write_string_p3
nop
control_flow_trap_p3:
j control_flow_trap_p3
nop
bcd_storage_p3:
.space 10 #creates 10 words here
invalid_char_p3:
.asciiz "Error: Invalid character "
control_message_p3:
.asciiz "Error: Program entered project3_print.asm due to missing control flow at the end of main.asm "
project3_print:
push $ra
beq $a1, $0, UART_no_error_p3 # Check for error
nop
li $a0, invalid_char_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 \0
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
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
