根据数字是正数还是负数修改寄存器

Modifying a register based on whether a number is positive or negative

我是汇编和 MIPS 的新手,想练习一下我的技能。我在网上找到了一些练习,并决定试一试。以下是我不太确定的一个:

Set the value stored in $t0 to -1, if $t0 is negative, and 0 if $t0 is positive.

我的方法是否正确?这可以使用算术移位更有效地完成吗?

这是我的代码:

main:
    li $t0, -5
    bgt $t0, [=10=], pos

    # must be negative
    li $t1, -1
    # negative so make t0 = -1
    srav $t0, $t0, $t1

    # end of program
    li $v0, 10
    syscall


pos:
    # positive so make t0 = 0
    sra $t0, $t0, 31

    # end of program
    li $v0, 10
    syscall

sra by 31 广播符号位,创建 0(所有位清除)或 -1(所有位设置,在二进制补码系统如 MIPS 上为 -1)。

没有必要围绕它进行分支,并且您已经在分支的两侧进行了相同的转换。算术右移 reg_width - 1(或在可能的 ISA 上更多 1)会将整个寄存器变成原始符号位的副本。原始 MSB 在 LSB 结束,其余位是该位的副本。

脚注 1: 它不在 MIPS 上。从寄存器中获取计数的 MIPS 移位仅使用低 5 位作为计数 (MIPS32 instruction-set reference manual),因此 -1 & 31 = 31。当然,立即计数移位在 R 型指令编码中只有一个 5 位 shamt 字段。


所以非负数(正数和零)变成0,负数变成-1

li 一个 -1 作为一个 srav 的计数而不是仅仅做 sra $t0, $t0, 31 是非常奇怪的。或者因为你显然只想将 $t0li $t0, 0move $t0, $zer0 归零,如果你正在分支并且知道你想要那里的 0。或者没有伪指令,or $t0, $zero, $zero)


这个技巧是众所周知的(在位黑客爱好者和编译器开发人员中),并用于许多位黑客,例如无分支absInteger absolute value in MIPS?

(MIPS 有其他无分支条件指令,如 slt / sltu,后来的 MIPS movnmovs 无分支条件移动指令。一些编译器使用它们对于绝对值:https://godbolt.org/z/eEzYKv3az)