10

您是否有任何简单的方法可以将 MIPS 中的寄存器中的值作为绝对值?

4

5 回答 5

22

这是一个无分支的变体:

# input and output in $t0
sra $t1,$t0,31   
xor $t0,$t0,$t1   
sub $t0,$t0,$t1    

这是如何运作的?
首先,$t1用 的符号位填充$t0。因此如果$t0为正$t1将设置为 0,如果$t0为负$t1将设置为 0xFFFFFFFF。

接下来,如果为 0xFFFFFFFF,则 的每一位都$t0被反转$t1,如果为 0,则保持不变$t1。恰好反转一个数字的所有位与将其设置为相同(-number)-1(在二进制补码中)。

最后,从中间结果中减去 0xFFFFFFFF(等于 -1)或 0。

因此,如果$t0最初是负数,您将得到:
$t0 = ($t0 ^ 0xFFFFFFFF) - 0xFFFFFFFF== (-$t0 - 1) - -1== (-$t0 - 1) + 1== -$t0
如果它最初是积极的,你会得到:
$t0 = ($t0 ^ 0) - 0== $t0

于 2013-04-17T12:20:44.457 回答
14

这是一个非常简单的方法。

#assume you want the absolute value of r1
        ori $2, $zero, $1      #copy r1 into r2
        slt $3, $1, $zero      #is value < 0 ?
        beq $3, $zero, foobar  #if r1 is positive, skip next inst
        sub $2, $zero, $1      #r2 = 0 - r1
foobar:
#r2 now contains the absolute value of r1
于 2010-02-22T17:10:55.443 回答
9

最简单的方法。有一个伪指令可以做到这一点:

abs $t1, $t1

将获取寄存器 $t1 中值的绝对值并将其放入 $t1

于 2013-10-27T03:43:03.187 回答
2

这是它的尺寸优化版本。由于分支预测问题,它比 sra/xor/subu 答案慢,但它的指令更小:

    bgtz $t0, label
label:
    subu $t0, $zero, $t0

这是因为 MIPS 延迟槽起作用的:如果$t0为正,则subu取反指令$t0执行两次。您可能需要.set noreorder在您的汇编程序中启用。

于 2015-08-08T00:51:41.140 回答
1

最简单的方法就是对值进行一些二进制数学运算。

http://en.wikipedia.org/wiki/Signed_number_representations描述了各种系统如何存储它们的负数。我相信 MIPS 使用二进制补码方案来存储带符号的数字。这使得它比位标志更难,可以通过将数字与 0b01111111 进行与运算来关闭它,但它仍然是可行的。

于 2010-02-22T17:01:33.973 回答