I have been working on a code that takes three strings, copies one string into another, takes the length of one of the strings, then concatenates the three strings, copies them, and get there length, but there is a problem. I need it to display 'The three strings combined are: I love assembly. When string 4 is copied into string 6, string 6 is: I love assembly. The length of string 6 is: 15. When string 3 is copied into string 5, string 5 is: assembly. The length of string 1 is: 2.' But instead of getting this, I am getting 'The three strings combined are: ssemblyy. When string 4 is copied into string 6, string 6 is: ssemblyy. The length of string 6 is: 268501001. When string 3 is copied into string 5, string 5 is: ssemblyy. The length of string 1 is: 17.' What is wrong? I tried contacting my teacher, but I haven't had a response at all, so I'm at a loss

.data
.align 4
S1: .asciiz "I "
S2: .asciiz "love "
S3: .asciiz "assembly"
string1: .asciiz "The first string is:\n"
string2: .asciiz "\nThe second string is:\n"
string3: .asciiz "\nThe third string is:\n"
string4: .space 16
string5: .space 9
string6: .space 16
S4: .asciiz "\nThe three strings combined are: "
S5: .asciiz "\nWhen string 3 is copied into string 5, string 5 is: "
S6: .asciiz "\nWhen string 4 is copied into string 6, string 6 is: "
L1: .asciiz "\nThe length of the first string is: "
L2: .asciiz "\nThe length of string 4 is: "
.text
main:
    #display all three strings first
    li $v0, 4
    la $a0, string1
    syscall
    la $a0, S1
    syscall
    la $a0, string2
    syscall
    la $a0, S2
    syscall
    la $a0, string3
    syscall
    la $a0, S3
    syscall
    #display the three string when concatenated, as well as copied into S6, and their length
    la $s0, string4
    la $s1, S1
    la $s2, S2
    la $s3, S3
    jal strcatFirst
    jal printConcat
    addi $a2, $a1, 0
    addi $v1, $v0, 0
    addi $v0, $0, 11
    la $s0, S4
    syscall
    jal printConcatCopy
    addi $s2, $s1, 0
    addi $v1, $v0, 0
    addi $v0, $0, 11
    la $s0, S6
    syscall
    jal printConcatLength
    addi $a2, $a1, 0
    addi $v1, $v0, 0
    addi $v0, $0, 11
    la $s0, L2
    syscall
    #display string 5 when string 3 is copied into it
    la $s1, string5
    la $s2, S3
    jal strcpy    
    jal print2
    addi $s2, $s1, 0
    addi $v1, $v0, 0
    addi $v0, $0, 11
    la $s0, S5
    syscall
    #display length of string 1
    la $a0, S1 #load address of string
    jal strlen #call string length procedure
    move $a0, $v0
    jal print4
    addi $a1, $a0, 0 #move address of string to $a1
    addi $v1, $v0, 0 #move length of string to $v1
    addi $v0, $0, 11 #syscall code for message
    la $a0, L1 #address of message
    syscall
    li $v0, 10
    syscall

strcatFirst:
    lb $t0, ($s1)
    beqz $t0, strcatSecond
    sb $t0, ($s0)
    addi $s1, $s1, 1
    addi $s0, $s0, 1
    j strcatFirst

strcatSecond:
    lb $t0,($s2)
    beqz $t0, strcatThird
    sb $t0, ($s1)
    addi $s2, $s2, 1
    addi $s1, $s1, 1
    j strcatSecond

strcatThird:
    lb $t0, ($s3)
    beqz $t0, endStrcat
    sb $t0, ($s2)
    addi $s3, $s3, 1
    addi $s2, $s2, 1
    j strcatThird

endStrcat:
    jr $ra
printConcat:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, S4
    syscall
    li $v0, 4
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra

strcpy:
    lbu $t0, 0($s2) #load a byte from source string
    beqz $t0, cpyExit #stop when null is copied
    sb $t0, 0($s1) #store byte in destination string
    addi $s2, $s2, 1 #increment both addresses
    addi $s1, $s1, 1

    j strcpy


cpyExit:
    jr $ra

print2:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, S5
    syscall
    li $v0, 4
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra

printConcatCopy:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, S6
    syscall
    li $v0, 4
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra

printConcatLength:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, L2
    syscall
    li $v0, 1
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra                
 strlen:
    move $t0, $zero #initialize count to start with 0 for first character
    j strlen.test
strlen.loop:
    addi $a0, $a0, 1 #load increment string pointer
    addi $t0, $t0, 1 #increment count
strlen.test:
    lb $t1, 0($a0) #load the next character to t0
    bnez $t1, strlen.loop #end loop if null character is reached
    move $v0, $t0
    jr $ra
print4:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, L1
    syscall
    li $v0, 1
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra

Recommended Answers

All 5 Replies

One thing I noticed is that I made a mistake in the stack saves, when I first showed you about them, and all the function which use them have duplicated the error. instead of

sw $ra, 0($fp)

you should use

sw $ra, 4($fp)

You would make the same change to the load statements for the $ra register.

Also, in many cases, I figured out a way to avoid using the $s0 register as swap space, but it does mean an extra load cycle. Instead of saving the $s0 and copying $a0 to $s0, you can simply save $a0 to the stack directly and load it back when you need it:

print4:
    addi $sp, $sp, -12
    sw $fp, 0($sp)
    move $fp, $sp 
    sw $ra, 4($fp)
    sw $a0, 8($fp)

    li $v0, 4
    la $a0, L1
    syscall
    li $v0, 1
    lw $a0, 8($fp) # retrieve the argument from the stack
    syscall

    lw $ra, 4($fp)
    lw $fp, 0($sp)
    addi $sp, $sp, 12
    jr $ra

I doubt it will have a significant impact on the problem you're having but it might.

Part of the problem you are having is that you aren't concatenating S2 and S3 to S1 in string4; instead, you are overwriting the copy of S1 with S2, then overwriting that with S3. Basically, you are losing track of what registers you are using for what purpose. In strcatSecond and strcatThird (which I still say should be successive calls to a single function!), you should continue using $s0 as the destination pointer (actually, you should be using $a0, but we've gone over that already) in the successive sub-functions:

strcatFirst:
    lb $t0, ($a1)
    beqz $t0, strcatSecond
    sb $t0, ($a0)
    addi $a1, $a1, 1
    addi $a0, $a0, 1
    j strcatFirst

strcatSecond:
    lb $t0,($a2)
    beqz $t0, strcatThird
    sb $t0, ($a0)
    addi $a2, $a2, 1
    addi $a0, $a0, 1
    j strcatSecond

strcatThird:
    lb $t0, ($a3)
    beqz $t0, endStrcat
    sb $t0, ($a0)
    addi $a3, $a3, 1
    addi $a0, $a0, 1
    j strcatThird

endStrcat:      
    sb $zero, 0($a0)       # ensure that the string is zero-delimited
    jr $ra

The other problem, that of why it prints a duplicate 'y', is more puzzling to me: for some reason, in your main function, you are calling system call 11 on the the last character of S4, then doing the same with S5 and S6 later on. These syscalls are completely unneeded and detrimental to the goal.

Okay, I took one of your previous suggestion, and rewrote the code. Yet still, my display is all wrong. I'm not going to bother saying what I need it to display(I've already said several times). Instead of displaying what I need, now I am getting: 'The three strings combined are: . The three strings combined are: . When S4 is copied into S6, S6 is: . The length of S4 is: 4268501299. When S3 is copied into S5, S5 is: . When S3 is copied into S5, S5 is: . The length of S1 is: 2. The length of S1 is: .' What have I done wrong now? And how do I get rid of the duplicates?

.data
.align 4
S1: .asciiz "I "
S2: .asciiz "love "
S3: .asciiz "assembly"
string1: .asciiz "The first string is:\n"
string2: .asciiz "\nThe second string is:\n"
string3: .asciiz "\nThe third string is:\n"
string4: .space 16
string5: .space 9
string6: .space 16
S4: .asciiz "\nThe three strings combined are: "
S5: .asciiz "\nWhen string 3 is copied into string 5, string 5 is: "
S6: .asciiz "\nWhen string 4 is copied into string 6, string 6 is: "
L1: .asciiz "\nThe length of the first string is: "
L2: .asciiz "\nThe length of string 4 is: "
.text
main:
    #display all three strings first
    li $v0, 4
    la $a0, string1
    syscall
    la $a0, S1
    syscall
    la $a0, string2
    syscall
    la $a0, S2
    syscall
    la $a0, string3
    syscall
    la $a0, S3
    syscall
    #display the three string when concatenated, as well as copied into S6, and their length
    la $a0, string4
    la $a1, S1
    la $a2, S2
    la $a3, S3
    jal strcat
    jal printS4
    la $a0, S4
    syscall
    jal printS6
    la $a0, S6
    syscall
    move $a0, $v0
    jal printL2
    la $a0, L2
    syscall
    #copy S3 into S5
    la $a1, string5
    la $a0, S3
    jal strcpy
    move $a0, $v0
    jal printS5
    addi $a1, $a0, 0
    addi $v1, $v0, 0
    la $a0, S5
    syscall
    #display length of S1
    li $v0, 4
    la $a0, S1
    jal strlen
    move $a0, $v0
    jal printL1
    addi $a1, $a0, 0
    addi $v1, $v0, 0
    li $v0, 4
    la $a0, L1
    syscall
    li $v0, 10
    syscall

strcat:
    addi $sp, $sp, -12
    sw $fp, 0($sp)
    move $fp, $sp
    sw $ra, 4($sp)
    sw $a0, 8($fp)

    jal strlen
    lw $a0, 8($fp)
    add $a0, $a0, $v0
    jal strcpy
    lw $v0, 8($fp)
    lw $ra, 4($fp)
    lw $fp, 0($sp)
    addi $sp, $sp, 12

    jr $ra

strlen:
    move $t0, $zero
    j strlen.test
strlen.loop:
    addi $a0, $a0, 1
    addi $t0, $t0, 1
strlen.test:
    lb $t1, 0($a0)
    bnez $t1, strlen.loop
    move $v0, $t0
    jr $ra

strcpy:
    move $v0, $a0
strcpy.loop:
    sb $t0, 0($a0)
    addi $a1, $a1, 1
    addi $a0, $a0, 1
strcpy.test:
    lbu $t0, 0($a0)
    bnez $t0, strcpy.loop
strcpy.exit:
    jr $ra

printS4:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0
    li $v0, 4
    la $a0, S4
    syscall
    move $a0, $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($fp)
    addi $sp, $sp, 12
    jr $ra
printS5:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0
    li $v0, 4
    la $a0, S5
    syscall
    move $a0, $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($fp)
    addi $sp, $sp, 12
    jr $ra
printS6:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0
    li $v0, 4
    la $a0, S6
    syscall
    move $a0, $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($fp)
    addi $sp, $sp, 12
    jr $ra
printL1:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, L1
    syscall
    li $v0, 1
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra
printL2:
    addi $sp, $sp, -12
    sw $fp, 8($sp)
    addi $fp, $sp, 16
    sw $ra, 0($fp)
    sw $s0, -4($fp)
    move $s0, $a0 # store the argument in a save register
    li $v0, 4
    la $a0, L2
    syscall
    li $v0, 1
    move $a0, $s0 # retrieve the argument from $s0
    syscall
    lw $s0, -4($fp)
    lw $ra, 0($fp)
    lw $fp, 8($sp)
    addi $sp, $sp, 12
    jr $ra

I probably shouldn't do this but, I've gone through the code and removed all the extraneous system calls (which were the source of the duplicate lines) and fixed a number of issues in the code as well. I even simplified the print functions, coalecing them into just two functions of two arguments each.

.data
.align 4
S1: .asciiz "I "
S2: .asciiz "love "
S3: .asciiz "assembly"
string1: .asciiz "The first string is:\n"
string2: .asciiz "\nThe second string is:\n"
string3: .asciiz "\nThe third string is:\n"
string4: .space 16
string5: .space 9
string6: .space 16
S4: .asciiz "\nThe three strings combined are: "
S5: .asciiz "\nWhen string 3 is copied into string 5, string 5 is: "
S6: .asciiz "\nWhen string 4 is copied into string 6, string 6 is: "
L1: .asciiz "\nThe length of the first string is: "
L2: .asciiz "\nThe length of string 4 is: "
.text
main:
    #display all three strings first
    li $v0, 4
    la $a0, string1
    syscall
    la $a0, S1
    syscall
    la $a0, string2
    syscall
    la $a0, S2
    syscall
    la $a0, string3
    syscall
    la $a0, S3
    syscall

    #display the three string when concatenated, as well as copied into S6, and their length
    la $a0, string4
    la $a1, S1
    jal strcat
    move $a0, $v0
    la $a1, S2
    jal strcat
    move $a0, $v0
    la $a1, S3
    jal strcat
    la $a0, S4
    move $a1, $v0
    jal printmessage

    la $a0, string6
    la $a1, string4
    jal strcpy
    la $a0, S6
    move $a1, $v0
    jal printmessage

    la $a0, string4
    jal strlen
    la $a0, L2
    move $a1, $v0
    jal printlength

    #copy S3 into S5
    la $a0, string5
    la $a1, S3
    jal strcpy
    la $a0, S5
    move $a1, $v0
    jal printmessage

    #display length of S1
    li $v0, 4
    la $a0, S1
    jal strlen
    la $a0, L1
    move $a1, $v0
    jal printlength
    li $v0, 10
    syscall

strcat:
    addi $sp, $sp, -12
    sw $fp, 0($sp)
    move $fp, $sp
    sw $ra, 4($sp)
    sw $a0, 8($fp)

    jal strlen
    lw $a0, 8($fp)
    add $a0, $a0, $v0
    jal strcpy
    lw $v0, 8($fp)
    lw $ra, 4($fp)
    lw $fp, 0($sp)
    addi $sp, $sp, 12

    jr $ra

strlen:
    move $t0, $zero
    j strlen.test
strlen.loop:
    addi $a0, $a0, 1
    addi $t0, $t0, 1
strlen.test:
    lb $t1, 0($a0)
    bnez $t1, strlen.loop
    move $v0, $t0
    jr $ra

strcpy:
    move $v0, $a0
    j strcpy.test
strcpy.loop:
    addi $a1, $a1, 1
    addi $a0, $a0, 1
strcpy.test:
    lbu $t0, 0($a1)
    sb $t0, 0($a0)  
    bnez $t0, strcpy.loop
strcpy.exit:
    jr $ra

printmessage:
    li $v0, 4
    syscall
    move $a0, $a1
    syscall
    jr $ra

printlength:
    li $v0, 4
    syscall
    li $v0, 1
    move $a0, $a1
    syscall
    jr $ra

Thanks. I hope this works, 'cause I've only got until 11:59 PM this Sunday to submit the code and get much needed extra credit points.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.