开发者

Convert C to MIPS - Nested Arrays

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


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:

lw  $t0, 16($s7)   # gets the value of B[4]
                   # offset could be 4 depending on memory width
                   # but then the shift would not be needed
sll $t0, $t0, 2    # this multiplies the index by 4 to get the address offset
add $t0, $t0, $s6  # adds the base address of A and the offset
lw  $t0, 0($t0)    # loads the value at the address
sub $s0, $s1, $t0  # performs subtraction and stores in f

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.


As pointed out my many there was an error in the book. Since discovering this error I found several such errors.


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

  lw  $s0, 0($t0)

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜