我面前有一个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
这是解决这个问题的正确方法吗?
2条答案
按热度按时间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)<=y
与z<y
是一样的。第一个
如果
z
是无符号的,则无法进行优化,编译器只会递增,然后使用双指令<=
slt/xori序列的无符号版本:第一个
其他关系
完全相等,
a == b
不相等,
a != b
一个非零整数:
a!=0
,即!!a
任何其他的都可以很明显地被派生出来,或者只是问一个编译器(使用Godbolt链接)。
t9eec4r02#
正如Michael所指出的,您应该将标签放在下面一行中,如下所示:
有趣的是,您使用了
slt
而没有使用seq
,为什么不呢?您可能会这样做:通过避免分支,程序可以稍微快一点(假设这种情况发生很多次)。