pfinferno
pfinferno

Reputation: 1945

converting a C for loop to MIPS

I'm trying to make this C code translated directly to mips, without modifying any instructions, to make it run better:

for(i = 0; i != j; i += 2)
    b[i] = a[i] - a[i + 1]

I'm not really going to be coding in mips, I'm just trying to understand some things. Here's what I have so far (not much):

#t5 = i
$t6 = j
#t1 = a
#t2 = b
#t3 = c
#t10, t11, t12 = free

add $t5, $zero, $zero # initialize i = 0 

loop:
    bne $t5, $t6        # check if i is not equal to j
    addi $t5, $t5, 2    # i += 2
    add $t10, $t5, $t11 # temp reg $t10 = address of b[i]
    lw $t2, 0($t10)     # temp reg $t2 = b[i]
    add $t10, $t5, $t12 # temp reg $t10 = address of a[i]
    lw $t1, 0($t10)     # temp reg $t1 = a[i]

Not sure if the bne is right, since I didn't specify anywhere to branch to. I've read up on arrays in mips but it confuses me. I know I need to use the proper offset for byte addressing when putting the arrays in the registers. Would it be the same with a variable instead of a number in the array? Any direction or tips would be nice. Thank you!

Upvotes: 5

Views: 6202

Answers (2)

joel reindel
joel reindel

Reputation: 85

Don't forget that the memory addressing is offset by 4 bits for word reading. According to the text Computer Organization and Architecture, the correct way to move through the array indexed by i is to do:

sll $t10,$t5,2     #$t10=i*4
add $t10,$t10,$t1  #$t10 = i*4 + addr(a)
lw $t11,4($t10)    #temp reg $t11 = a[i + 1]
lw $t12,0($t10)    #temp reg $t12 = a[i]

Notice that i must be multiplied by 4 and the offset for the lw should be in multiples of 4. If this is not done, the addressing will not progress properly because the addressing is bytewise, but we are using wordwise data manipulation. The correct implementation would look like this.

#t5 = i
#t6 = j
#t1 = address of a
#t2 = address of b
#t10, t11, t12 = free

#START
move $t5,$0               #set $t5 to zero

loop:
       bne $t5,$t6,exit   #if $t5 not equal to $t6 branch to exit
       sll $t10,$t5,2     #temp reg $t10 = i*4
       add $t10,$t10,$t1 #temp reg $t10 = address of a[i]
       lw $t11,4($t10)    #temp reg $t11 = a[i + 1]
       lw $t12,0($t10)    #temp reg $t12 = a[i]
       sub $t10,$t12,$t11 #temp reg $t10 = a[i] - a[i + 1]
       sll $t11,$t5,2     #temp reg $t11 = i*4
       add $t11,$t11,$t2  #temp reg $t11 = address of b[i]
       sw $t10,0($t11)    #store word b[i] = a[i] - a[i + 2]
       addi $t5,$t5,2     #i+=2
       j loop             #jump to start of loop
exit

Upvotes: 1

8tracklover
8tracklover

Reputation: 26

You guessed right, bne needs a location to branch to. So you need at least one more tag in your program. In the example below, that new tag is called "exit".

As far as the addressing in loading and storing, I agree with you; it can get a little confusing at first (especially if you're used to c style array indexing). If your offset is not a constant, then you have to perform an add (or subtract) operation to get the address. Let's use the address of a[i + 1] as an example: first you need to add the address of a to i and store it somewhere, then you can load (or store) to the true address by using the constant offset. I rewrote your example so that you could see what I'm talking about; it's one of those things that's easier to see by example than by explanation :)

#t5 = i
#t6 = j
#t1 = address of a
#t2 = address of b
#t10, t11, t12 = free

#START
move $t5,$0               #set $t5 to zero

loop:
       bne $t5,$t6,exit   #if $t5 not equal to $t6 branch to exit
       addi $t10,$t1,$t5  #temp reg $t10 = address of a[i]
       lw $t11,1($t10)    #temp reg $t11 = a[i + 1]
       lw $t12,0($t10)    #temp reg $t12 = a[i]
       sub $t10,$t12,$t11 #temp reg $t10 = a[i] - a[i + 1]
       addi $t11,$t2,$t5  #temp reg $t11 = address of b[i]
       sw $t10,0($t11)    #store word b[i] = a[i] - a[i + 2]
       addi $t5,$t5,2     #i+=2
       j loop             #jump to start of loop
exit:

Upvotes: 1

Related Questions