I am studying the MIPS assembly language and came across this example in the book and to me it seems incorrect. If it is it wouldn't be the first mistake I found in this book.
The variables f
and g
are assigned registers $s0
and $s1
respectively, the base addresses for the arrays A
and B
are $s6
and $s7
respectively.
The c code example is:
f = g - A[B[4]];
And the corresponding MIPS assembly provided is:
lw $t0, 16($s7)
lw $s0, 0($t0)
sub $s0, $s1, $s0
From my understanding the above MIPS code would load some random data from memory at the address provided by $t0
and then subtract it from $s1
and not access the index $t0
of the array denoted in $s6
.
The correct MIPS assembly from my understanding would be along the lines of:
lw $t0, 4($s7)
add $t0, $t0, $s6
sll $t0, $t0, 2
lw $s0, 0($t0)
sub $s0, $s1, $s0
I am correct that this is an error in the book or am I misunderstanding something.
Edit: Fixed an error in the corrected mips code as pointed out by Chris Dodd
As pointed out my many there was an error in the book. Since discovering this error I found several such errors.
This is for anyone (possibly CprE 381 students) who may stumble upon this looking for a good example. The OP's edited code is still incorrect. The offset in the first load word function should be 16. It could be 4 if the memory width is 32 bits, but then the shift/multiplication would not be needed. Assuming the memory is 8 bits wide, the add and shift functions need to be switched. In OP's code, it's multiplying the address of A[B[4] / 4] by 4. Shifting/multiplying first will get the correct index. The correct code is:
In case anyone is confused about the whole offset of 16 vs 4 and whether the shift is needed, let me explain. If the memory width is 32 bits then an entire 32-bit integer can be stored in one memory location. If this is the case, then the array index is the same as the address offset. However, if the memory is only 8 bits (1 byte) wide, then a 32-bit integer is stored across 4 memory locations (1 address for each byte). This is why you need to shift the index by 2 (or multiply by 4) to get the correct address offset.
But it could very well be that the author copied the code before link time. This would leave open the possibility that the linker fills in the memory address of A[] in place of the 0 in the statement
in the final executable. I don't know if MIPS allows offsets of that size (that is, the address range where A[] is being placed finally). This of course is no nice way to explain something in a book, breaking one's own premises silently and generally not knowing what is going on.