Arrays and lw/sw


Consider the following C code segment:

        /* Initialize every other element in array A to 0 */
        /* (assume numVals is number of values in A) */
        int i;
        for ( i = 0; i < numVals; i += 2 )
            A[i] = 0;


MIPS translation using array indexing:

Assume that $a0 holds A (address of beginning of array), and $a1 holds numVals.
        move $t0, $zero

LOOP:   slt $t1, $t0, $a1
        beq $t1, $zero, ENDLP

        sll $t2, $t0, 2
        add $t3, $a0, $t2
        sw  $zero, 0($t3)

        addi $t0, $t0, 2
        j LOOP
ENDLP:  ...
# $t0 = i = 0

# $t1 = 1 if i < numVals
# leave loop if i >= numVals

# $t2 = 4 * i
# t3 = A + 4i, i.e., &A[i]
# store 0 out to A[i]

# i += 2
# jump to top of loop
Addresses Memory: Addressable Bytes
1000 (A[0]) 00000000000000000000000000000000
1004 (A[1]) --------------------------------
1008 (A[2]) 00000000000000000000000000000000
1012 (A[3]) --------------------------------
1016 (A[4]) --------------------------------
1020 (A[5]) --------------------------------
1024 (A[6]) --------------------------------
1028 (A[7]) --------------------------------
1032 (A[8]) --------------------------------
1036 (A[9]) --------------------------------
    Step 1: i=0, t2=0, t3=1000, store 32 0's to A[0]
    Step 2: i=2, t2=8, t3=1008, store 32 0's to A[2]
    -----------
    Step 3: i=4, t2=16, t3=1016, store 32 0's to A[4]
    Step 4: i=6, t2=24, t3=1024, store 32 0's to A[6]
    Step 5: i=8, t2=32, t3=1032, store 32 0's to A[8]


What's the deal with the lw/sw offset?

The instruction
    sw $zero, 0($t3) 
means: "store the contents of $zero in memory at address $t3 + 0". Why did we need to calculate $t3 = A + $t2? Why couldn't we just use A as the base address and $t2 as the offset?
    sw $zero, $t2($a0)
Syntax: the offset has to be a constant. When stepping through an array, we don't have a constant offset, so we have to calculate the exact address and then use a 0 offset.

Is the lw/sw offset ever useful?

Yes, but not when stepping through arrays.

Stack example

Assume that $sp is 2048, $ra holds 32772, $a0 holds 1026, and $a1 holds 85.
PROC:   addi $sp, $sp, -12
        sw  $ra, 0($sp)
        sw  $a0, 4($sp)
        sw  $a1, 8($sp)
          ...
        lw  $a1, 8($sp)
        lw  $a0, 4($sp)
        lw  $ra, 0($sp)
        addi $sp, $sp, 12
        jr $ra
# adjust $sp to 2036 for 3 values
# save $ra to 2036
# save $a0 to 2040
# save $a1 to 2044
# ... procedure contents here ...
# restore $a1 from 2044
# restore $a0 from 2040
# restore $ra from 2036
# adjust $sp back to 2048
# jump back to calling routine
Addresses Memory: Addressable Bytes
2020  --------------------------------
2024  --------------------------------
2028  --------------------------------
2032  --------------------------------
2036  00000000000000010000000000000100
2040  00000000000000000000010000000010
2044  00000000000000000000000001010101
2048  --------------------------------
2052  --------------------------------
2056  --------------------------------


Alyce Brady, Kalamazoo College