assembly - 将 C 数组操作转换为汇编

标签 assembly mips

我正在努力尝试将 a[i+1] = a[i-1] + b[4] 转换为汇编。其中$s0a的地址,$s1b的地址,$ s2 是变量i。教授提到可以通过 6 个步骤完成。

我有:

addi $t0, $s2, 4 #i + 1

addi $t1, $s2, -4 #i - 1

lw $t2, $t1($s0) #load a[i-1] - I know this is wrong

lw $t3, 16($s1) #load b[4]

add $t4, $t2, $t3 #add a[i-1] + b[4]

sw $t4, $t0($s0) #save to a[i+1] - I know this is wrong

我知道哪里出了问题,我知道我不能立即使用寄存器,但我不确定如何解决这个问题。我也可能这样做完全错误,并且感谢任何帮助。

最佳答案

这里是一些我相信可以工作的带注释的代码:

    .text

    .globl  main
# main -- main program
#
# a[i + 1] = a[i - 1] + b[4]
#
# arguments:
#   s0 -- address of a
#   s1 -- address of b
#   s2 -- i
#
# registers:
#   t0 -- address of a[i]
#   t1 -- value of b[4]
#   t2 -- i << 2 (i.e. a byte offset)
#   t3 -- value of a[i - 1]
#   t4 -- a[i - 1] + b[4]
main:
    sll     $t2,$s2,2               # get i << 2
    add     $t0,$s0,$t2             # get &a[i]

    lw      $t3,-4($t0)             # get a[i - 1]
    lw      $t1,16($s1)             # get b[4]

    add     $t4,$t3,$t1             # sum them
    sw      $t4,4($t0)              # a[i + 1] = sum

这非常接近可以使用的唯一序列。 lw 指令的顺序可以翻转,但除此之外,指令必须与所示的顺序相同,除非使用不同的寄存器来保存不同的值。

为了清晰度,每个中间术语/步骤都有自己的t寄存器。但是,如果重新分配/重用寄存器,我们可以减少使用的寄存器数量。例如,在前两条指令中,我们可以将 $t2 替换为 $t0,因为此后我们再也不会使用 $t2

优化编译器可以/将会做到这一点。我们最终只需要 $t0-$t2 而不是 $t0-$t4:

    .text

    .globl  main
# main -- main program
#
# a[i + 1] = a[i - 1] + b[4]
#
# arguments:
#   s0 -- address of a
#   s1 -- address of b
#   s2 -- i
#
# registers:
#   t0 -- i << 2
#         address of a[i]
#   t1 -- value of b[4]
#   t2 -- value of a[i - 1]
#         sum of a[i - 1] + b[4]
main:
    sll     $t0,$s2,2               # get i << 2
    add     $t0,$s0,$t0             # get &a[i]

    lw      $t2,-4($t0)             # get a[i - 1]
    lw      $t1,16($s1)             # get b[4]

    add     $t2,$t2,$t1             # sum them
    sw      $t2,4($t0)              # a[i + 1] = sum

如果代码是函数的一部分,我们可以使用 $v0, $v1, $a0 作为我们的临时寄存器,因为函数允许使用 $v0-$v1$a0-$a3 作为内部临时变量(如果愿意的话)。


更新:

The comments definitely help me understand what is occurring during each instruction

良好的编程风格[因此理解]有很多评论。类型正确。这对于 asm 尤其重要,因为在 C 中,像 number_of_users 这样的变量在某种程度上具有描述性。但是,$t0 不是。

我添加的注释是我为自己编写的任何 asm 代码所做的。而且,我编写汇编已经有几十年了。

此外,“优化”版本还有一个目的:简化。通过释放 $t3-$t4,它们可以用来存放其他东西。在更复杂的函数中,这可以区分简单且易于理解的函数和难以理解和维护的不必要的复杂函数。

有关这方面的更多信息,以及根据我自己的经验如何写好汇编的技巧,请参阅我的答案:MIPS linked list

the professor is not the greatest at relaying information

在类环境中可以传达的信息有限。它可以涵盖基础知识。而且,类(class)作业可以帮助您学习给定语言的基础知识。而且,在我看来,教授们从来都不太擅长很好地注释代码[足够了;-)]。

当我[在不同的架构上]学习 asm 时,除了类(class)作业之外,我还能够在 100% 用 asm 编写的多用户分时操作系统上担任付费程序员。它的评论风格与上面相同。

IMO,最好的学习方法之一是分析“专家”代码。问这样的问题:“他们为什么要那样做?”。我就是这样做的,并且学到了很多东西。直到今天,我[仍然]对那次经历表示赞赏。

关于assembly - 将 C 数组操作转换为汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39261059/

相关文章:

Windows 内核 - 是否有类似 ExGetPoolsForTag(pool_tag) 的东西?

mips - 什么是 MIPS 首字母缩略词中的 "interlocked pipeline"?

assembly - MIPS 流水线阶段

assembly - 为什么MIPS不能在寻址模式下使用两个寄存器?

arrays - MIPS 中的二维数组

c - 遵循简单的内核教程时出现奇怪的链接器错误 gcc

c++ - 从程序集中调试用户的崩溃

assembly - itoa 负数?

string - 在 Assembly x86 中将数字字符串转换为整数

gcc - 带有用于 MS-Windows 的工具链的预构建 MIPS 交叉编译器