assembly 如何在汇编语言(MIPS)中做小于或等于?

ulmd4ohb  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(459)

我面前有一个C代码,我必须把它翻译成MIPS汇编语言。
我并不想得到一个直接的答案,但我希望有人能纠正我对这个问题的看法。
我面前的C代码是:

x = ((++z)<=y);

在给定的情况下,x、y和z分别存储在寄存器 *$6、$7、$8中 *
问题是我不能使用运算符直接比较小于或等于。我只能使用下面的比较操作数:好的,好的,好的,好的。
我处理这个问题的方式是这样的:

addi   $8,$8,1     #this will increment z by 1 to have ++z
      slt    $1,$8,$7    #compares ++z to y if ++z is < than y, it will store 1 in $1
      beq    $8,$7,Label #compares if $8 = $7, if so the code jumps to Label
Label addi   $t0,$0,1    #if ++z = y, stores 1 in $t0
      ori    $6,$t0,$1   #Or's the t0 and t1 and accordingly stores 0 or 1 in x

这是解决这个问题的正确方法吗?

b91juud3

b91juud31#

像往常一样,询问编译器(例如在Godbolt编译器资源管理器上)。

单独的<=(没有增量)最好通过反转slt(执行b<a,它与a<=b相反)和**然后xori**来翻转结果来实现。

第一个
有趣的事实是:RISC-V的clang做了同样的事情,slt/xori,因为RISC-V就像MIPS一样,只提供了slt用于比较到布尔值(因为你可以布尔化任何关系,比如==,〈=,〉,或者其他任何关系到一个整数寄存器,最多有2条指令)。
但是在你想要递增的情况下,你使用addi,很明显z必须是一个有符号的int(否则你的代码会在从0x 7 fffffffU到0x 80000000 U的递增中出错;如果您想要定义明确回绕,请使用addiu)。

C中符号溢出为未定义行为的规则基本上与MIPS addi的使用相匹配,这意味着编译器也会假设++z不换行,并执行我们想要的优化。他们和我们可以只使用原始z值。如果z+1不/不能换行,(z+1)<=yz<y是一样的。

第一个
如果z是无符号的,则无法进行优化,编译器只会递增,然后使用双指令<= slt/xori序列的无符号版本:
第一个

其他关系

完全相等,a == b

xor     $2,$4,$5          # find bit-differences
    sltu    $2,$2,1           # (a^b) < 1U

不相等,a != b

xor     $2,$4,$5
    sltu    $2,$0,$2          # 0U < (a^b)

一个非零整数:a!=0,即!!a

sltu    $2,$0,$4          # 0U < a

任何其他的都可以很明显地被派生出来,或者只是问一个编译器(使用Godbolt链接)。

t9eec4r0

t9eec4r02#

正如Michael所指出的,您应该将标签放在下面一行中,如下所示:

addi   $8,$8,1
         slt    $1,$8,$7
         beq    $8,$7,Label
         addi   $t0,$0,1
Label    ori    $6,$t0,$1

有趣的是,您使用了slt而没有使用seq,为什么不呢?您可能会这样做:

addi   $8,$8,1
         slt    $1,$8,$7
         seq    $t0,$8,$7
         ori    $6,$t0,$1

通过避免分支,程序可以稍微快一点(假设这种情况发生很多次)。

相关问题