我面前有C代码,我必须将其翻译成MIPS汇编语言。
我并不寻求直接的答案,但我希望有人能纠正我思考这个问题的方式。
我面前的C代码是:
x = ((++z) <= y);
字符串
在给定的情况下,x、y和z分别存储在寄存器 $6、$7、$8 中。
问题是我不能使用运算符直接比较小于或等于。我只能使用以下比较操作数:bne,beq,ori,slt.
我处理这个问题的方法是这样的:
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
型
这是解决这个问题的正确方法吗?
1条答案
按热度按时间wfveoks01#
像往常一样,询问编译器(例如Godbolt编译器资源管理器上)。参见How to remove "noise" from GCC/clang assembly output?
<=
单独(没有增量)最好使用反向slt
(执行与a<=b
相反的b<a
)和**然后xori
**来翻转结果。个字符
有趣的事实:RISC-V的clang做了同样的事情,slt/xori,因为RISC-V就像MIPS一样,只提供
slt
用于比较到布尔值。(因为你可以用最多2条指令将任何关系,如==、<=、>或其他任何关系布尔化到整数寄存器中。但是在你想要递增的情况下,你使用的是
addi
,所以很明显z必须是一个有符号的int(否则你的代码在从0x 7 fffffffU递增到0x 80000000 U时会出错;使用addiu
,如果你想要良好定义的环绕)。**针对signed-overflow的C规则基本上与MIPS
addi
的使用相匹配,这意味着编译器也会假设++z
没有 Package **,并进行我们想要的优化。他们和我们我们可以只使用原始的z值。如果z+1
不能换行,则(z+1)<=y
与z<y
是一样的。的字符串
如果
z
是无符号的,那么这种优化是不可能的,编译器只是递增,然后使用2指令<=
slt/xori序列的无符号版本:的字符串
其他关系
完全相等,
a == b
型
不相等,
a != b
型
一个非零整数:
a!=0
,即!!a
型
任何其他的显然都可以派生,或者只需要询问编译器(使用Godbolt链接)。