简体   繁体   中英

Java to MIPS assembly convert (recursive method)

I am trying to implement a recursive modular exponentiation program in MIPS assembly. The program lets the user input three positive numbers x, n and p, and outputs (x^n) mod p. I was able to write the code for it in Java, but I am having a difficult time converting that code to MIPS Assembly. Here is my Java code:

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;
}

I realize that my biggest issue is calling methods in MIPS, especially recursively. Here is what I have so far:

.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

I use syscall instructions to take the input from the user and to output things to the user. Doing most of the arithmetic is simple enough, most of my trouble is with these method calls, especially in recursion. Can anyone help me?

In your Java-code, you're recursively calling modPow() , which operates on its function arguments, but in your assembly-code, you're recursing into main() , which does I/O. This is probably not what you want. Define a label modPow: and implement your function there. Also, the Java-code is more complicated than it needs to, which in turn makes implementing it unnecessarily difficult.

1. If your if -condition ends in a return statement, you don't need an else
2. You don't need to calculate the modulo if you're not going to use it.
3. You don't need to calculate the modulo in two places (in function body and recursive call). You do want to calculate the modulo for your return value, though.
4. pow(1,n) is 1 for all n.
5. pow(0,n) is 0 for all n!=0 (arguable, but already covered by if (!n) )

Try:

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);
}

That said, to call a function on MIPS, you need to save the current value of the link register (return address) on the stack:

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

There are 2 rules to recursion:

  1. Save your return address

    • This is the address of the function that called you and this is usually register $ra. Save this on the stack, (not in one of the save registers - $s0...7)
  2. Jump and link (jal) to the method you want to call

I think the problem your code has is that you don't seem to be doing either of these

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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