将 C 转换为 MIPS - 嵌套数组

发布于 2024-12-07 14:04:01 字数 768 浏览 0 评论 0原文

我正在学习 MIPS 汇编语言,并在书中看到了这个例子,对我来说这似乎是不正确的。如果是的话,这将不是我在本书中发现的第一个错误。

变量fg分别被分配到寄存器$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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鸠魁 2024-12-14 14:04:01

这适用于任何可能偶然发现此内容并寻找好例子的人(可能是 CprE 381 学生)。 OP编辑的代码仍然不正确。第一个加载字函数中的偏移量应该是16。如果存储器宽度是32位,则可以是4,但是这样就不需要移位/乘法了。假设存储器是8位宽,则需要切换加法和移位功能。在OP的代码中,它将A[B[4] / 4]的地址乘以4。首先移位/相乘将得到正确的索引。正确的代码是:

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

如果有人对 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:

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.

浅紫色的梦幻 2024-12-14 14:04:01

正如我所指出的,书中有一个错误。自从发现这个错误以来,我发现了几个这样的错误。

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

初懵 2024-12-14 14:04:01

但很可能作者在链接时间之前复制了代码。这可能会导致链接器填充 A[] 的内存地址来代替

  lw  $s0, 0($t0)

最终可执行文件中语句中的 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

  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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文