I need to write a procedure in MIPS that will find the length of two input string arguments. After that the procedure needs to add the shorter string to the bigger one,calculate its length and print the whole string. Then write a main function that will test procedure so that you complete the processes: input strings from the keyboard, calling the procedure and print the length of the new array screen.
I store both names in separate registers, but I need to combine them to one before I print the full name out.
code:
.data
first:.asciiz "First string: \n"
last:.asciiz "Second string: \n"
full:.asciiz "Full string: "
.text
main:
# first string
li $v0, 4 # 4 prints a line
la $a0, first # Print first string text
syscall # Syscall
add $a1, $a1, 254 # Setting String length
li $v0, 8 # 8 will read string
syscall # calls the word
sw $v0, first
move $v0, $t1 # The string is now in $t1
# second string
li $v0, 4 # 4 prints a line
la $a0, last # Print second string text
syscall # Syscall
li $v0, 8 # 8 will read string
syscall # calls the word
sw $v0, last
move $v0, $t2 # The string is now in $t2
# Full string
li $v0, 4 # 4 prints a line
la $a0, full # Print the whole text
syscall
You'll need to to prompt, strip newline, and calculate string length for both of your input strings. You should also have separate string buffers for input strings and the combined output string.
Here's some working code:
.data
first: .asciiz "First string: "
last: .asciiz "Second string: "
full: .asciiz "Full string: "
newline: .asciiz "\n"
string1: .space 256 # buffer for first string
string2: .space 256 # buffer for second string
string3: .space 512 # combined output buffer
.text
main:
# prompt and read first string
la $a0,first # prompt string
la $a1,string1 # buffer address
jal prompt
move $s0,$v0 # save string length
# prompt and read second string
la $a0,last # prompt string
la $a1,string2 # buffer address
jal prompt
move $s1,$v0 # save string length
# point to combined string buffer
# NOTE: this gets updated across strcat calls (which is what we _want_)
la $a0,string3
# decide which string is shorter based on lengths
blt $s0,$s1,string1_short
# string 1 is longer -- append to output
la $a1,string1
jal strcat
# string 2 is shorter -- append to output
la $a1,string2
jal strcat
j print_full
string1_short:
# string 2 is longer -- append to output
la $a1,string2
jal strcat
# string 1 is shorter -- append to output
la $a1,string1
jal strcat
# show results
print_full:
# output the prefix message for the full string
li $v0,4
la $a0,full
syscall
# output the combined string
li $v0,4
la $a0,string3
syscall
# finish the line
li $v0,4
la $a0,newline
syscall
li $v0,10
syscall
# prompt -- prompt user for string
#
# RETURNS:
# v0 -- length of string (with newline stripped)
#
# arguments:
# a0 -- address of prompt string
# a1 -- address of string buffer
#
# clobbers:
# v1 -- holds ASCII for newline
prompt:
# output the prompt
li $v0,4 # syscall to print string
syscall
# get string from user
li $v0,8 # syscall for string read
move $a0,$a1 # place to store string
li $a1,256 # maximum length of string
syscall
li $v1,0x0A # ASCII value for newline
move $a1,$a0 # remember start of string
# strip newline and get string length
prompt_nltrim:
lb $v0,0($a0) # get next char in string
addi $a0,$a0,1 # pre-increment by 1 to point to next char
beq $v0,$v1,prompt_nldone # is it newline? if yes, fly
bnez $v0,prompt_nltrim # is it EOS? no, loop
prompt_nldone:
subi $a0,$a0,1 # compensate for pre-increment
sb $zero,0($a0) # zero out the newline
sub $v0,$a0,$a1 # get string length
jr $ra # return
# strcat -- append string
#
# RETURNS:
# a0 -- updated to end of destination
#
# arguments:
# a0 -- pointer to destination buffer
# a1 -- pointer to source buffer
#
# clobbers:
# v0 -- current char
strcat:
lb $v0,0($a1) # get the current char
beqz $v0,strcat_done # is char 0? if yes, done
sb $v0,0($a0) # store the current char
addi $a0,$a0,1 # advance destination pointer
addi $a1,$a1,1 # advance source pointer
j strcat
strcat_done:
sb $zero,0($a0) # add EOS
jr $ra # return
Well, it seems like you have some missconceptions about syscall 8
. You have to load $a0 with the address of input buffer, and $a1 with maximum number of characters to read.
In your code, you are telling syscall that the input buffer will override first
's contents, and that is fine. But, at this point, $v0 is 8, and sw $v0, first
will write 0x8 in first
and, therefore, in $a0
. So you just lost your string.
This should work:
1) start reserving space for both input buffers. This can be done as firstread: .space 254
. Do the same with lastread: .space 254
.
2) load firstread
in $a0 and 253
in $a1, \n's space should be reserved. Use syscall
to read the string to firstread's address.
3) load lastread
in $a0 and keep the value of $a1. use syscall to read the string to lastread's address.
At this point, you have both strings readed and stored in memory. You don't know the size of each, so you'll have to iterate over them counting the number of bytes until you find a null byte (0x0) in each. The rest is easy. You can easily thell which is larger or smaller looking at the number of bytes. Try doing it and let me know if you don't succeed.