Sum of an array
The same program in M68K, RISC-V, Z80, x86.
The assembler writes six numbers next to one another in memory. Rather than give each word a
separate label, this program keeps the address of the next word in $t0 and adds each value to a
running total in $t2.
numbers names the first word. The six .word values take 24 bytes, so the assembler places end
at its current location immediately after the sixth word. The label takes no space of its own.
la $t1, end therefore gives the program the address where it should stop.
.data
numbers: .word 4, 8, 15, 16, 23, 42
end:
.text
main:
la $t0, numbers # address of the next element
la $t1, end # address one past the array
li $t2, 0 # running total
loop:
beq $t0, $t1, done # check before loading, so an empty array is valid
lw $t3, 0($t0) # load the element under the pointer
addu $t2, $t2, $t3 # add this word to the total
addiu $t0, $t0, 4 # advance to the next word
j loop
done:
li $v0, 10 # exit
syscall
At loop, $t0 points to the next word and $t1 marks the stopping address. beq checks those
addresses before lw reads memory. If they differ, lw reads the word at $t0, addu adds it
to $t2, and addiu advances $t0 by four bytes to the next word. lw itself does not move the
pointer. The jump repeats the check. addu and addiu do their arithmetic without stopping on
signed overflow; the six values here give the ordinary sum 108.
Run the program. The important stopping check is that $t0 equals $t1: the pointer reached
end without trying to load from it. $t2 should hold 108 and $t3 should still hold the last
word, 42. The register panel shows hexadecimal without a 0x prefix, so those values appear as
0000006C and 0000002A. In this Playground layout, numbers begins at 0x10010000; after six
four-byte words, both pointers show 10010018. $v0 shows 0000000A for the exit syscall.
For a second check, make the array empty by changing the data declarations to these two adjacent labels:
numbers:
end:
Also add li $t3, 0x12345678 immediately after li $t2, 0, then run again. The first beq should
go directly to done: $t2 stays 0, $t0 equals $t1, and $t3 keeps the sentinel value
0x12345678 because no lw ran.
Finally, restore the six values, remove the sentinel line, and add , 100 after 42 on the
.word line. The total becomes 208 without changing an instruction: the assembler moves end to
the address after the new last word.