何时在MIPS汇编语言中使用临时寄存器和保存的寄存器?

4

In this question:

x = x + y - 10 - A[20]

x - $s0
y - $s1
A - $s3

我的回答是:

add   $t0,   $s0,   $s1    # value of x ($s0) + y ($s1) gets stored in temp $t0
addi  $t0,   $t0,  - 10    # subtracts value of $t0 from 10. $t0 now holds the new value
lw    $t1,   80($s3)       # loads value of A[20] into new temp $t1
sub   $s0,   $t0,  $t1     # subtracts values $t0 from $t1 and stores it in x 
                           ($s0)

然而,模型解决方案显示:
add   $s0,   $s0,   $s1   
addi  $s0,   $s0,  - 10    
lw    $t0,   80($s3)   
sub   $s0,   $s0,  $t0

我的原始答案正确吗?它不会输出相同的结果吗?如果我错了,请解释为什么。

2个回答

4
何时使用MIPS汇编语言中的临时寄存器和保留寄存器?
附加说明彼得·科德斯的答案。
MIPS汇编的通用调用约定要求您保留“saved”寄存器中的值,并使您可以修改“temporary”寄存器,这在从代码调用子例程时会生效。
由于临时寄存器可以被子程序自由修改,因此如果需要该值,则必须在子程序调用周围保存/恢复它们,因此在子例程调用之间经常使用临时寄存器来存储具有有限生命周期的值。
相反,“saved”寄存器必须由您的代码保留,以不对上面的调用者进行修改,即每当您使用另一个新的saved寄存器时,您应该将其原始值放置在某个地方(通常是堆栈内存)),然后在返回给调用者之前恢复它。这会带来轻微的性能损失,因此除非您调用多个子例程并且通过在saved寄存器中具有更长寿命的值而不必在每个调用周围保留/恢复它们而获得性能,否则可能要完全避免使用“saved”寄存器在您的代码中。
因此,按照以下经验法则:
1. 根本不使用寄存器/值(通过更聪明的算法或代码结构来消除,更好地重用已受影响的寄存器) 2. 对于有限生命周期的值,尤其是它们不会与子程序调用冲突的情况下,使用临时寄存器。 3. 对于在子例程调用期间必须保留的值(特别是几个子例程调用),请使用saved寄存器。
(这是定义的“调用约定”,即您可以定义+使用自己的约定,从而违反了临时/保存寄存器使用规则..这不是内置于CPU中的设计)

2
两个答案都是正确的;有许多方法可以编译该表达式,使用任何寄存器以及不同的操作顺序或不同的指令选择。
将结果写入指令作为输入读取的寄存器没有任何缺点。如果周围代码更多作为大函数的一部分,使用较少的暂存器可能是一个优势。如果您考虑到寄存器分配压力作为大函数的一部分,那么模型解决方案可能比您的更优。
但由于周围没有代码,没有理由说你的代码有什么问题。也许将原始的x值保留更长时间是有用的。
重新排列以缩短关键路径延迟,并在超标量CPU上使用指令级并行性(例如MIPS r10k是4路超标量,具有乱序执行)。
需要三个加/减运算,在你的问题中,两个版本都存在串行依赖,需要通过所有三个ALU操作。
二进制补码算术是可交换的。但MIPS的“add”操作对于有符号溢出会出现故障,因此创建临时结果很重要(就像FP舍入误差一样)。但MIPS还有“addu”,它会进行包装而不是故障,因此如果您不关心有符号溢出时引发异常,则可以使用“addu”/“addiu”/“subu”,然后可以重新排序操作为“(x - A [20])+(y-10)”,例如。
lw    $t0,   80($s3)       # load as early as possible
addiu $t1,   $s1,  -10     # y-10 in the shadow of the load delay slot
subu  $s0,   $s0,  $t0     # x-A[20]
addu  $s0,   $s0,  $t1

请注意,变量x$s0)直到第三条指令才需要准备好,因此我们可以隐藏一些x输入的延迟。如果您知道操作数来自哪些指令,请按照需要最后使用的顺序安排操作,这样最后可能准备好的操作数会最后使用。(特别是如果您正在为类似r10k的顺序CPU进行调整)
当然,如果您预计某些负载延迟,那么在使用加载结果之前尽可能完成所有ALU工作更有意义,即使这意味着通过使它们相互依赖来串行化所有三个加/减操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接