Cristian RPI
Cristian RPI

Reputation: 35

How to save string into an array in mips

I have a problem with this code. I try to enter a string by input and save it into an array, this my code:

    .data
    .align 2
array:  .space 80
size: .word 20
string: .space 20
op: .asciiz "Enter the array length"
prompt: .asciiz "Enter a string:"
text:   .asciiz "The array of string is:"
newline: .asciiz "\n"
    .text
    .globl main

main:
    add $t0, $zero, $zero # index of array
    addi $t1, $zero, 1 # counter=1

    li $v0, 4
    la $a0, op
    syscall
    jal new_line

    li $v0, 5
    syscall

    addi $s0, $v0, 0 # $v0 contains integer read
read_string: 
    bgt $t1, $s0, L1 # if ($t1 > length)then go to L1

    li $v0, 4
    la $a0, prompt
    syscall

    la $a0, string
    li $a1, 20
    li $v0, 8
    syscall

    sw $a0, array($t0)
    addi $t0, $t0, 4
    addi $t1, $t1, 1

    j read_string

L1: #### here i want to print the array ####
    add $t0, $zero, $zero # index of array
    addi $t1, $zero, 1 # counter=1

    la $a0, text
    li $v0, 4
    syscall
    jal new_line

    while: bgt $t1, $s0, done
    lw $t2, array($t0)

    li $v0, 4
    move $a0, $t2
    syscall
    jal new_line

    addi $t0, $t0, 4
    addi $t1, $t1, 1
    j while

    new_line: la $a0, newline
    li $v0, 4
    syscall
    jr $ra

done: li $v0, 10
    syscall

The trouble is that this program show me the last string that I've entered by input, for example

Enter the array length:
2
Enter a string:asd
Enter a string:123
The array of string is:
123

123

Please I need some help, thanks a lot and have a nice day.

Upvotes: 0

Views: 13486

Answers (1)

Craig Estey
Craig Estey

Reputation: 33601

Your array indexing logic appears to be okay, but the problem was that you were always storing every entry with the same address, the address of string. The solution is a larger string area and incrementing a pointer to it when storing the strings.

I've corrected your code [untested]. Please pardon the gratuitous style cleanup, but I needed to understand your logic before trying to fix it. I've added more comments [I'm an old time asm guy, and I always comment every line] and annotated your code with [OLD] and my replacements with [NEW].

    .data
    .align 2
array:      .space  80
size:       .word   20
###string:  .space  20          # [OLD]
string:     .space  20000       # [NEW]
op:         .asciiz "Enter the array length:"
prompt:     .asciiz "Enter a string:"
text:       .asciiz "The array of string is:"
newline:    .asciiz "\n"

    .text
    .globl main
main:
    # prompt user for array length
    li      $v0,4
    la      $a0,op
    syscall
    jal     new_line            # output newline

    # read in array count
    li      $v0,5
    syscall
    addi    $s0,$v0,0           # $v0 contains the integer we read

    add     $t0,$zero,$zero     # index of array
    addi    $t1,$zero,1         # counter=1
    la      $s2,string          # load address of string storage area [NEW]

read_string:
    bgt     $t1,$s0,L1          # if ($t1 > length) then array is done -- fly

    # prompt the user for next "string"
    li      $v0,4
    la      $a0,prompt
    syscall

    # get the string
### la      $a0,string          # place to store string [OLD]
    move    $a0,$s2             # place to store string [NEW]
    li      $a1,20
    li      $v0,8
    syscall

    # store pointer to string into array
    sw      $a0,array($t0)

    addi    $t0,$t0,4           # advance offset into pointer array
    addi    $t1,$t1,1           # advance iteration count
    addi    $s2,$s2,20          # advance to next string area [NEW]

    j       read_string

#### here i want to print the array ####
L1:
    add     $t0,$zero,$zero     # index of array
    addi    $t1,$zero,1         # counter = 1

    # output the title
    la      $a0,text
    li      $v0,4
    syscall
    jal     new_line

while:
    bgt     $t1,$s0,done        # more strings to output?  if no, fly
    lw      $t2,array($t0)      # get pointer to string

    # output the string
    li      $v0,4
    move    $a0,$t2
    syscall
    jal     new_line

    addi    $t0,$t0,4           # advance array index
    addi    $t1,$t1,1           # advance count
    j       while

# new_line -- output a newline char
new_line:
    la      $a0,newline
    li      $v0,4
    syscall
    jr      $ra

# program is done
done:
    li      $v0,10
    syscall

UPDATE For extra credit, when you get the original version working, you can try replacing addi $s2,$s2,20 with jal stradv, where stradv is:

# stradv -- advance past end of string
stradv:
    ldb     $t2,0($s2)          # get char
    addi    $s2,$s2,1           # we pre-increment because we want EOS + 1
    bne     $t2,$zero,stradv    # is it EOS?  if no, loop some more
    jr      $ra

This would allow large variable length strings [if you also increased the length on the string read syscall].

This is how I normally would have coded something like this, but I didn't want to add this until you had the basic code fully working.

Upvotes: 3

Related Questions