[英]Java to MIPS assembly convert (recursive method)
我正在尝试在MIPS程序集中实现递归模幂运算程序。 该程序允许用户输入三个正数x,n和p,并输出(x ^ n)mod p。 我能够用Java编写代码,但是我很难将代码转换为MIPS Assembly。 这是我的Java代码:
int modPow(int x, int n, int p) {
x = x%p;
if (n == 0)
return 1;
else if (n == 1)
return x;
else if (n%2 == 0)
return modPow(x*x%p, n/2, p);
else
return x*modPow(x, n-1, p)%p;
}
我意识到我最大的问题是在MIPS中调用方法,特别是递归。 这是我到目前为止:
.text
main:li $v0, 5 #store x in $v0
syscall
move $s0, $v0 #move x to $s0
li $v0, 5 #store n in $v0
syscall
move $s1, $v0 #move n to $s1
li $v0, 5 #store p in $v0
syscall
move $s2, $v0 #move p to $s2
div $s0, $s2
mfhi $s0 #x = x % p
bne $s1, $zero, L1 #Branch to first ElseIf if !(n==0)
li $a0, 1 #return value stored as 1
li $v0, 1 #output 1 (what is stored in $a0)
syscall
L1: li $t0, 1 #$t0 = 1
bne $s1, $t0, L2 #Branch to second ElseIf if !(n==1)
move $a0, $s1 #$a0 = n
li $v0, 1 #output n (stored in $a0)
syscall
L2: li $t0, 2 #t0 = 2
div $s1, $t0
mfhi $t0 #$t0 = n % 2
bne $t0, $zero, L3 #Branch to else if !(n%2==0)
mflo $s1 #$s1 = floor(n/2)
mult $s0, $s0 #x * x
mfhi $s0 #x = x * x
div $s0, $s2
mfhi $s0 #$s0 = (x * x) % p
jal main
L3: li $t0, 1 #$t0 = 1
sub $s1, $t0 #n = n-1
jal main
mult $s0, $a0 #x * mod(x, n-1, p)
mfhi $s0 #x = x * mod(x, n-1, p)
div $s0, $s2
mfhi $a0 #x = x * mod(x, n-1, p) % p stored in $a0
li $v0, 1
syscall
我使用系统调用指令来获取用户的输入并将内容输出给用户。 做大部分算术都很简单,我的大多数麻烦都是用这些方法调用,特别是在递归中。 谁能帮我?
在你的Java代码中,你递归地调用modPow()
,它运行在它的函数参数上,但在你的汇编代码中,你正在递归到main()
,它执行I / O. 这可能不是你想要的。 定义标签modPow:
并在那里实现您的功能。 此外,Java代码比它需要的更复杂,这反过来又使得实现它变得不必要地困难。
1.如果if
以return
语句结束,则不需要else
2.如果你不打算使用它,你不需要计算模数。
3.您不需要在两个位置计算模数(在函数体和递归调用中)。 但是,您确实希望计算返回值的模数。
所有n的pow(1,n)为1。
5.对于所有n!= 0,pow(0,n)为0(可论证,但已被if (!n)
覆盖)
尝试:
int modPow(int x, int n, int p)
{
if (!n)
return 1;
x %= p;
if ( !x || x == 1 || n ==1 )
return x;
if (n % 2)
return x*modPow(x, n-1, p)%p;
return modPow(x*x, n/2, p);
}
也就是说,要在MIPS上调用函数,需要在堆栈上保存链接寄存器(返回地址)的当前值:
addi $sp, $sp, -4 #on 32-bit MIPS, 4 byte word
sw $ra, ($sp) #save return address of current function
... #load function arguments to $a0...
jal functionToCall #call
... #use return value in $v0
lw $ra, ($sp) #restore return address
addi $sp, $sp, 4 #restore stack-pointer
jr $ra #return
递归有两个规则:
保存您的寄信人地址
跳转并链接(jal)到您要调用的方法
我认为你的代码存在的问题是你似乎没有做过这些
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.