我的最终目标是以这种方式用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等。
我的问题:
所有案例制作此分支和链接的简单方法是什么?
我的意思是,如果发生了某种情况,请分支到标签,并将$ +的地址存储在$ ra中,以便我可以返回我的代码?
另外,我不能创建另一个标签来代表程序的其余部分(并跳转它),我必须在$ ra中以某种方式返回,因为它是从基于java的代码转换mips
感谢。
答案 0 :(得分:4)
对于这个例子
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的操作方式,而有条件地执行某些指令则是针对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(我确实错过了&lt; =,&gt; =,... by pseudo ins的存在并且产生了不太好的部分答案,现在编辑它以更准确和完整):
还有伪指令sle / sge / seq / sne for&lt; =,&gt; =,==,!=。
出于我自己的好奇心,我不得不看看它们是如何实现的,基本上是:
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
但我不清楚为什么你可以做这个,并且不能做正确的事情,看起来很奇怪,你可能有一些非常奇怪的情况(基本上我不相信你,你可能错过了如何在没有标签的注入代码中进行分支的方式,所以你认为它不可能,但只要你注入代码就可以了就像在你的问题中一样,你也可以在注入短代码的范围内注入&#34;其余代码&#34; target。
如果你真的必须这样做,那么考虑将它全部移动到子程序,因此主代码只有jal set_t1_when_r1_equals_r2
,并且li
都将在子程序中。这至少有点可维护,上面的例子非常糟糕。
但&#34;由条件设置&#34;当然,解决方案优于任何分支。