将 C 转换为 MIPS - 嵌套数组
我正在学习 MIPS 汇编语言,并在书中看到了这个例子,对我来说这似乎是不正确的。如果是的话,这将不是我在本书中发现的第一个错误。
变量f
和g
分别被分配到寄存器$s0
和$s1
,数组的基地址< code>A 和 B
分别是 $s6
和 $s7
。
C 代码示例是:
f = g - A[B[4]];
提供的相应 MIPS 程序集是:
lw $t0, 16($s7)
lw $s0, 0($t0)
sub $s0, $s1, $s0
根据我的理解,上面的 MIPS 代码将从 $t0
提供的地址处的内存中加载一些随机数据,然后从 中减去它$s1
并且不访问 $s6
中表示的数组的索引 $t0
。
根据我的理解,正确的 MIPS 汇编应该是这样的:
lw $t0, 4($s7)
add $t0, $t0, $s6
sll $t0, $t0, 2
lw $s0, 0($t0)
sub $s0, $s1, $s0
我是正确的,这是书中的一个错误,或者我误解了某些东西。
编辑:修复了 Chris Dodd 指出的更正 mips 代码中的错误
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这适用于任何可能偶然发现此内容并寻找好例子的人(可能是 CprE 381 学生)。 OP编辑的代码仍然不正确。第一个加载字函数中的偏移量应该是16。如果存储器宽度是32位,则可以是4,但是这样就不需要移位/乘法了。假设存储器是8位宽,则需要切换加法和移位功能。在OP的代码中,它将A[B[4] / 4]的地址乘以4。首先移位/相乘将得到正确的索引。正确的代码是:
如果有人对 16 与 4 的整个偏移量以及是否需要移位感到困惑,让我解释一下。如果内存宽度为 32 位,则可以将整个 32 位整数存储在一个内存位置中。如果是这种情况,则数组索引与地址偏移量相同。但是,如果存储器只有 8 位(1 字节)宽,则 32 位整数将存储在 4 个存储器位置(每个字节 1 个地址)。这就是为什么您需要将索引移动 2(或乘以 4)才能获得正确的地址偏移量。
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.
正如我所指出的,书中有一个错误。自从发现这个错误以来,我发现了几个这样的错误。
As pointed out my many there was an error in the book. Since discovering this error I found several such errors.
但很可能作者在链接时间之前复制了代码。这可能会导致链接器填充 A[] 的内存地址来代替
最终可执行文件中语句中的 0。我不知道MIPS是否允许该大小的偏移(即A[]最终放置的地址范围)。这当然不是解释书中某些内容的好方法,它默默地打破了自己的前提,而且通常不知道发生了什么。
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.