我试图解决这个问题并将其转换为 MIPS 汇编代码
但是书中的答案让我很困惑。所以,谁能解释一下这段代码是如何在 c 中得到这个结果的?
B[g] = A[f] + A[f+1];
我已经插入了我认为正确的评论,如果我错了请纠正我。
Assume we have variables f, g, h, i, j stored in $s0, $s1, $s2, $s3 and $s4, respectively. Assume the base addresses of arrays A and B are at $s6 and $s7.
代码:
add $t0, $s6, $s0 #This will add f bytes to the base address and it's not equal to A[f].
add $t1, $s7, $s1 #This will add g bytes to the base address and it's not equal to B[g]
lw $s0, 0($t0) #This will point to the value in (f +base address of A +0) bytes
lw $t0, 4($t0) #This will point to the value in (f +base address of A +4) bytes
add $t0, $t0, $s0
sw $t0, 0($t1)
你的编译片段由我注释:
add $t0, $s6, $s0
将寄存器s6
和s0
中的内容添加并存储在寄存器t0
中。由于您已经指出f
存储在s0
中,A
的基地址存储在s6
中,这会添加地址,为稍后的寄存器间接加载做准备。更简单的 A[f] == *(A + f)
在 C 中,这是为稍后的 (A + f)
取消引用做准备。
add $t1, $s7, $s1
同样的事情发生在 B
和 g
上。添加它们的内容并将它们存储在中间寄存器中,稍后用作基于地址的取消引用目标。
lw $s0, 0($t0)
这是加载到 s0
寄存器,使用所谓的 register-indirect
cpu 寻址模式,无论 指向的地址是什么t0
加上 0 个字节。在 c 中,这等于 s0 = *(A + f)
。
lw $t0, 4($t0)
和上面一样,只是这次它加载注册t0
指向t0
的任何内容加上4 个字节。等于 C t0 = *(A + f + 1)
。
add $t0, $t0, $s0
这是它在您的代码中执行加法的地方。相当于A[f] + A[f + 1]
的C代码片段。
sw $t0, 0($t1)
这是将之前加法的结果存储到t1
指向的地址中。
~~~~~~~~~~~
如果您正在寻找您所拥有的代码的一些引用资料,我发现这两个 MIPS instruction set reference useful当然,Matt Godbolt's interactive compiler .
如果您想使用交互式编译器查看哪些代码执行哪些操作,只需将您的代码包装在 void
函数中,选择编译器 x86 clang
并在编译器处选项 --target=mips
。然后从过滤器应用着色,你将能够看到什么 C 代码生成什么汇编代码,得到如下图所示的东西