我的最终目标是以这种方式在MIPS中编写代码
temp = 0; if (x == y) temp = 1 ...rest of the program...
我应该为==,!=,<=,> =,<,>写它
我想到了这样的事情:
li $t1 0 beq $r1 $r2 Temp1 /**rest of the program...**/ Temp1: li $t1 1 (1) /** how do I return to rest of the program? **/
我在mips中看到了BGEZAL命令(beq的insetad),该命令允许我放入(1)行
jr $ra
但我没有找到适合所有情况的命令:bge,bne,neq等。
我的问题 :
所有情况下进行此分支和链接的简单方法是什么?
我的意思是,如果发生某些情况,请分支到标签,并将pc + 4的地址存储在$ ra中,以便返回代码?
另外,我无法创建另一个标签来表示程序的其余部分(并跳转它),我必须在$ ra中以某种方式返回,因为它是从基于Java的代码到mips的转换
谢谢。
对于这个例子
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的惯用操作,而有条件地仅执行某些指令则违反了“这里有pc
集合,因此我将执行”。
但是您根本不需要分支(如果您的目标是根据条件将某个寄存器设置为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(我确实错过了伪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)
编辑1:如果您坚持使用较慢的$ 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
但我不明白你为什么能做到这样,能不能做正确的事情,似乎很奇怪,你可能有一些非常奇怪的情况(基本上我不相信你,你可能缺少的方式如何在没有标签的情况下在注入的代码中进行分支,因此您认为这是不可能的,但是,只要您可以像在问题中那样注入代码,就可以在注入的short范围内注入带有“其余代码”目标的分支码)。
而且,如果您确实必须执行此操作,则考虑将其全部移至子例程,这样主代码将是唯一的,jal set_t1_when_r1_equals_r2
并且两者li
将一起放在子例程中。那至少是可以维护的,上面的例子很糟糕。
但是,“按条件设置”解决方案当然要优于任何分支机构。