Do you have any simple ways to make a value in a register in MIPS as an absolute value?
问题:
回答1:
Here is a pretty simple way to do it.
#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
回答2:
Here's a branch-less variant:
# input and output in $t0
sra $t1,$t0,31
xor $t0,$t0,$t1
sub $t0,$t0,$t1
How does this work?
First, $t1
is filled with the sign-bit of $t0
. So if $t0
is positive $t1
will be set to 0, and if $t0
is negative $t1
will be set to 0xFFFFFFFF.
Next, each bit of $t0
is inverted if $t1
is 0xFFFFFFFF, or left unchanged if $t1
is 0. It just so happens that inverting all bits of a number is the same as setting it to (-number)-1
(in two's complement).
Finally, either 0xFFFFFFFF (which equals -1) or 0 is subtracted from the intermediate result.
So if $t0
originally was negative you'll get:
$t0 = ($t0 ^ 0xFFFFFFFF) - 0xFFFFFFFF
== (-$t0 - 1) - -1
== (-$t0 - 1) + 1
== -$t0
.
And if it originally was positive you'll get:
$t0 = ($t0 ^ 0) - 0
== $t0
.
回答3:
Simplest way of all. There is a pseudo instruction that does this:
abs $t1, $t1
will take the absolute value of the value in register $t1 and place it in $t1
回答4:
The easiest way would just to do a bit of binary math on the values.
http://en.wikipedia.org/wiki/Signed_number_representations describes how various systems store their negative numbers. I believe MIPS uses a two's complement scheme to store signed numbers. This makes it a bit harder than a bit flag, which could just be turned off by ANDing the number with 0b01111111, but it is still doable.
回答5:
Here's a size-optimized version of it. It's slower than the sra/xor/subu answer, due to branch prediction issues, but it's one instruction smaller:
bgtz $t0, label
label:
subu $t0, $zero, $t0
This works because of the MIPS delay slot: if $t0
is positive, the subu
instruction to negate $t0
executes twice. You may need to enable .set noreorder
in your assembler.