【问题标题】:psuedo MIPS branch and link command伪 MIPS 分支和链接命令
【发布时间】:2017-01-17 11:31:55
【问题描述】:

我的最终目标是以这种方式在 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/1,你不需要分支,对吧?
  • 是的。分支只是使用 bge、beq、bne(等等)命令的结果
  • 如果您可以为“temp1”代码创建标签,我看不出从基于 java 的翻译如何阻止您为其余代码创建另一个标签??

标签: assembly mips


【解决方案1】:

对于这个例子

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将在子程序中一起出现。这至少有点可维护,上面的例子很糟糕。

但“按条件设置”解决方案当然优于任何分支。

【讨论】:

  • 非常感谢。我认为对我来说最好和优雅的解决方案是使用 seq、sge、sgt、slt、sle、sne。我之前不知道这些说明
  • @Matan 哦.. 所以有 sle/seq/... 伪指令。我只打开了硬件参考卡,我没有弄清楚如何简单地做 sle/seq。现在我很好奇,这些是如何完成的......(但我没有 MIPS 汇编器 + 反汇编器)。无论如何,我很高兴它对你有所帮助。 :)
  • @Matan 原来我有一些虚弱的时刻.. sle r, x, y 实际上是微不足道的:r = !(y &lt; x) ... seqsne 更有趣,seq 完成为 @ 987654336@(3 条指令),sner = 0 &lt; |x-y|(2 条指令)。 (sg** 当然是 sl**,只是交换了 x 和 y)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
  • 2014-09-17
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多