MIPS- How to add one string to another

2019-09-14 11:34发布

问题:

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  

回答1:

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


回答2:

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.



标签: assembly mips