Vectors: indexing by position
A vector is an array: a sequence of numbers stored next to each other in memory. In the previous lesson you summed one by moving a pointer forward 4 bytes for each element. That same method works here. There is another common way to reach an element: by index. An index is the position of an element counted from the start, where the first element has index 0, the second has index 1, and so on.
Summing a vector by walking a pointer
.dataa: .word 5, 10, 15, 20 # four elements.textla t0, a # t0 = address of ali t1, 4 # t1 = number of elements leftli t2, 0 # t2 = running totalloop:beq t1, zero, donelw t3, 0(t0) # load current elementadd t2, t2, t3 # add to totaladdi t0, t0, 4 # advance to next word (4 bytes)addi t1, t1, -1 # one fewer leftj loopdone:mv a0, t2 # print total: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
The loop runs as follows. t0 holds the address of a, and t1 holds the number of elements remaining, starting at 4. On each pass, ends the loop when the count reaches zero. loads the element at the address in t0. adds that value to the running total. advances the pointer to the next word. decreases the count. After four passes (5 + 10 + 15 + 20), done prints 50. This is the same pattern used in the memory lesson, now applied to a vector.
From index to address
Indexing computes an address from a base pointer and a position: address = base + index * 4. The 4 is the size of a word in bytes. A compiler generates this same computation for a[i] in a language such as C. The index itself never accesses memory. Only the address computed from it does.
slli t5, t3, 2 # t5 = index * 4 (word size)add t6, t0, t5 # t6 = address of element[index]lw t6, 0(t6) # t6 = element[index]
shifts the index in t3 left by 2 bits, which multiplies it by 4 (two doublings: 2 x 2), the size of one word. Adding the result to the base pointer gives the address of element[index]. This shift is the same power-of-two method from the arithmetic lesson, and it is the standard way to scale an index by the size of a word.
a[0]: index 0, offset 0.
i as a position, and the address that position produces after scales it by 4 and adds it to the base. The hex numbers are the actual addresses that a occupies when the simulator runs this program. The aim is to predict the next address before it appears. That lets you read inside an incrementing loop, or a[i] in a C-like language, and picture the memory address it touches instead of treating the notation as a black box.Summing a vector by index
.dataa: .word 5, 10, 15, 20 # four elements.textla t0, a # t0 = base address of ali t1, 4 # t1 = number of elementsli t2, 0 # t2 = index, starts at 0li t3, 0 # t3 = running totalloop:beq t2, t1, doneslli t4, t2, 2 # t4 = index * 4 (byte offset)add t5, t0, t4 # t5 = address of a[index]lw t5, 0(t5) # t5 = a[index]add t3, t3, t5 # total += a[index]addi t2, t2, 1 # move to the next indexj loopdone:mv a0, t3 # print total: 5+10+15+20 = 50li a7, 1ecallli a7, 10ecall
The loop runs as follows. t2 is the index, starting at 0. On each pass, ends the loop when the index reaches 4, the element count held in t1. converts the index to a byte offset. adds that offset to the base address in t0 to produce the address of a[index]. loads the value stored there. That value is added to the running total in t3, and advances to the next index. After four passes (5 + 10 + 15 + 20), done prints 50.
Adding two vectors, element by element
.dataa: .word 3, 6, 9, 12 # first vectorb: .word 1, 2, 3, 4 # second vectorc: .space 16 # room for 4 result words.textla t0, a # base address of ala t1, b # base address of bla t2, c # base address of cli t3, 0 # index, starts at 0li t4, 4 # number of elementsli s0, 0 # running totalloop:beq t3, t4, doneslli t5, t3, 2 # byte offset = index * 4add t6, t0, t5 # address of a[index]lw t6, 0(t6) # value of a[index]add a0, t1, t5 # address of b[index]lw a0, 0(a0) # value of b[index]add t6, t6, a0 # a[index] + b[index]add a0, t2, t5 # address of c[index]sw t6, 0(a0) # c[index] = a[index] + b[index]add s0, s0, t6 # total += c[index]addi t3, t3, 1 # move to the next indexj loopdone:mv a0, s0 # print total: 4+8+12+16 = 40li a7, 1ecallli a7, 10ecall
The loop runs as follows. converts the index t3 to a byte offset. Adding it to each base pointer (t0, t1, t2) gives the addresses of a[i], b[i], and c[i]. On each pass, both elements are loaded, added together, stored into c, and added to the running total in s0. advances to the next index, and the loop repeats until all four elements are processed.
