对于这个例子
temp = 0;
if (x == y)
temp = 1
...rest of the program...
使用相反的分支更容易:
li $t1, 0
bne $r1, $r2, RestOfProgram ; temp already is 0, so only continue
; here you want temp=1, because x==y, so just set it, and continue
li $t1, 1
RestOfProgram:
...rest of the program...
所以你正在这样做:
temp = 0;
if (x != y) goto rest_of_program
temp = 1
rest_of_program:
...rest of the program...
(这是丑陋的伪 C,但在 ASM 中,这是更优雅和更干净的方式,因为“goto”是 ASM 的操作方式,而仅有条件地执行某些指令违反了“这里我有 @987654324”的 ASM 本质@set,所以我会执行它”)。
但你根本不需要分支(如果你的目标是通过条件将某个寄存器设置为 0 或 1),例如:
temp = (x < y);
slt $t1, $r1, $r2 ; or "sltu" for unsigned values
temp = (x > y)
slt $t1, $r2, $r1 ; or "sltu" for unsigned values
EDIT2(我确实错过了 =, ... by pseudo ins 的存在,并产生了不太好的答案部分,现在对其进行编辑以使其更加准确和完整):
对于=、==、!=还有伪指令sle/sge/seq/sne。
出于我自己的好奇心,我不得不看一下它们是如何实现的,基本上:
sgt: temp = (y < x) (slt with swapped arguments)
sle: temp = !(y < x) (slt, xori)
sge: temp = !(x < y) ("sle" with swapped arguments)
seq: temp = |x - y| < 1 (subu, $at=1, sltu)
sne: temp = 0 < |x - y| (subu, sltu $zero)
EDIT1:如果您坚持使用较慢的 $ra 子程序,则将整个测试移至 Temp1:
li $t1, 0
jal Temp1_when_equal
... rest of code ...
Temp1_when_equal: ; will set $t1 to 1 when $r1 == $r2
bne $r1, $r2, Temp1_keep_0
li $t1, 1
Temp1_keep_0:
jr $ra
但是我不清楚为什么你可以this,而不能做正确的事情,看起来很奇怪,你可能遇到了一些很奇怪的情况(基本上我不相信你,你可能错过了如何在没有标签的情况下在注入的代码中进行分支的方式,所以你认为这是不可能的,但是只要你可以像你的问题一样注入代码,你也可以在注入的短代码范围内注入带有“其余代码”目标的分支)。
如果你真的必须这样做,那么考虑把它全部移到子程序中,这样主代码将只有jal set_t1_when_r1_equals_r2,而li将在子程序中一起出现。这至少有点可维护,上面的例子很糟糕。
但“按条件设置”解决方案当然优于任何分支。