如何 return 到 MIPS 程序中的特定点

How to return to a specific point in a MIPS program

我正在 MIPS 中编写一个函数,它将存储在 a0-a3 寄存器中的两个分数相除,如下所示:(a0/a1) 和 (a2/a3)。我已经有一个函数可以将两个分数相乘,所以我需要做的就是切换第二个分数的分子和分母并调用我的乘法函数。我已经弄清楚了那部分,但是我还需要确保分子保留符号,这意味着如果我翻转第二个分数,它是负数,那么我需要将分子和分母都乘以 -1 .我已经编写了一个单独的函数来为我执行此操作,但是调用该函数后我不知道如何跳回到原来的位置。这是代码:

f_div:

#Flip the second fraction (a2/a3) -> (a3/a2)
add   $t0, $a2, [=11=]
add   $a2, $a3, [=11=]
add   $a3, $t0, [=11=]

ble   $a3, [=11=], f_flipsign #Branch if $a3 <= 0

#I need to be able to jump back here from f_flipsign
#How do I arbitrarily jump back to a location in the program without
#direct access to the PC?

add   $s0, $ra, [=11=] #Save $ra so I don't lose it when I jal f_mul 
jal   f_mul
add   $ra, $s0, [=11=] #Put the original $ra back 
# Also, is there a better way to do this ^

jr    $ra #Jump back to main

f_flipsign:

li    $t0, -1
mult  $a2, $t0
mflo  $a2
mult  $a3, $t0
mflo  $a2

jr  ? #How do I make this jump back to the middle of f_div?

我今天研究了好几个小时,但我似乎无法弄明白。我了解这些说明的格式,我只需要知道如何完成这一件事。非常感谢任何帮助,感谢您抽出宝贵时间。

如果您的 f_flipsign 子例程实际上是一些您只需要在这种情况下执行的代码,那么它可能根本不必是子例程只需更改分支条件并在那里添加翻转符号代码即可。

在这种情况下,只需将 ble 更改为 bgt 即可跳过翻转代码,例如:

  bgt   $a3, [=10=], dont_flip #Branch if $a3 > 0
# Your code to flip sign
  li    $t0, -1
  mult  $a2, $t0
  mflo  $a2
  mult  $a3, $t0
  mflo  $a2
dont_flip:
# Code continues here (whether it flipped sign or not)

如果flip_sign是一个可以从很多地方调用的子程序,那么你应该使用jal-code-jr,但你必须在某处(通常是堆栈)保存 $ra ,以便在调用子程序时不会丢失。 假设你保留了 $ra,那么你会这样写:

  bgt   $a3, [=11=], continue #Branch if $a3 > 0
  jal f_flipsign
continue:
# Code continues here (whether it flipped sign or not)

并且在您的 f_flipsign 子例程中结束于:

  jr $ra