我在MIPS中编写一个函数,它将分割存储在a0-a3寄存器中的两个分数,如:(a0 / a1)和(a2 / a3)。我已经有了一个将两个分数相乘的函数,所以我需要做的就是在第二个分数上切换分子和分母并调用我的乘法函数。我有那个部分想通了,但是我还需要确保分子保留符号,这意味着如果我翻转第二个分数,并且它是负数,那么我需要将分子和分母乘以-1 。我已经写了一个单独的函数为我做这个,但在调用该函数后,我不知道如何跳回到我的位置。这是代码:
f_div:
#Flip the second fraction (a2/a3) -> (a3/a2)
add $t0, $a2, $0
add $a2, $a3, $0
add $a3, $t0, $0
ble $a3, $0, 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, $0 #Save $ra so I don't lose it when I jal f_mul
jal f_mul
add $ra, $s0, $0 #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?
我今天研究和研究了几个小时,我似乎无法弄清楚这一点。我理解这些指令是如何格式化的,我只需要知道如何完成这一点。非常感谢任何帮助,感谢您抽出宝贵时间。
答案 0 :(得分:1)
如果您的 f_flipsign 子例程实际上是某些代码,您只需要在这种情况下执行,那么它可能根本不必是子例程,只需更改分支条件并添加在那里翻转标志代码。
在这种情况下,只需将ble
更改为bgt
即可跳过翻转代码,例如:
bgt $a3, $0, 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, $0, continue #Branch if $a3 > 0
jal f_flipsign
continue:
# Code continues here (whether it flipped sign or not)
并在你的f_flipsign子程序中结束:
jr $ra