C 到 MIPS 汇编

C to MIPS Assembly

我试图解决这个问题并将其转换为 MIPS 汇编代码 但是书中的答案令人困惑 me.so,谁能解释一下这段代码是如何在 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  # t0 = A + f
add $t1, $s7, $s1  # t1 = B + g
lw $s0, 0($t0)     # s0 = *(t0 + 0) = *(A + f) = A[f]
lw $t0, 4($t0)     # t0 = *(t0 + 4) = *(A + f + 1) = A[f+1]
add $t0, $t0, $s0  # t0 = t0 + s0 = A[f] + A[f+1]
sw $t0, 0($t1)     # *(t1 + 0) = *(B + g) = B[g] = t0

请记住,C 指针算法按项目大小缩放,但汇编使用字节。因此,前进 4 个字节在 C 中前进 1 项。

转念一想,这实际上意味着 fg 也应该按 4 缩放,但它们似乎不是。

我注释的你的编译片段:

add $t0, $s6, $s0  

将寄存器 s6s0 中的内容添加并存储在寄存器 t0 中。由于您已经指出 f 存储在 s0 中,而 A 的基地址存储在 s6 中,因此添加地址以准备稍后的寄存器间接加载在。在 C 中更简单的 A[f] == *(A + f),这是为稍后的 (A + f) 取消引用做准备。

add $t1, $s7, $s1  

Bg 也发生了同样的事情。添加它们的内容并将它们存储在中间寄存器中,稍后用作基于地址的取消引用目标。

lw $s0, 0($t0)     

这是加载到 s0 寄存器,使用所谓的 cpu 的 register-indirect 寻址模式,无论 t0 指向的地址是什么加上 0 个字节。在 c 中,这等于 s0 = *(A + f).

lw $t0, 4($t0)     

和上面一样,只是这次它加载到寄存器t0任何指向t0的东西加上4个字节。等于Ct0 = *(A + f + 1).

add $t0, $t0, $s0  

这是它在您的代码中执行加法的地方。等于A[f] + A[f + 1].

的C代码片段
sw $t0, 0($t1)

这是在t1所指向的地址中存放上次相加的结果。

~~~~~~~~~~~

如果您正在寻找您所拥有的代码的一些参考资料,我找到了这两个 MIPS instruction set reference useful and, of course, Matt Godbolt's interactive compiler

如果您想查看哪些代码使用交互式编译器执行哪些操作,只需将您的代码包装在 void 函数中,select 作为编译器 x86 clang 并在编译器选项中--target=mips。然后从滤镜中应用colourise,你将能够看到什么C代码生成什么汇编代码,得到如下图的东西

sll $t0, $s0, 2     # $t0 = f * 4
add $t0, $s6, $t0
sll $t1, $s1, 2     # $t1 = g * 4
add $t1, $s7, $t1
lw $s0, 0($t0)
lw $t0, 4($t0)
add $t0, $t0, $s0  
sw $t0, 0($t1)

是的,代码缺少这两行,您只需要将 fg 都缩放 4。