繁体   English   中英

Java到MIPS程序集转换(递归方法)

[英]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.如果ifreturn语句结束,则不需要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

递归有两个规则:

  1. 保存您的寄信人地址

    • 这是调用你的函数的地址,这通常是寄存器$ ra。 将其保存在堆栈中(不在其中一个保存寄存器中 - $ s0 ... 7)
  2. 跳转并链接(jal)到您要调用的方法

我认为你的代码存在的问题是你似乎没有做过这些

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM