I am in the process of trying to convert this C code to MIPS. This is only my second project so far and I feel like I am so close. Here is the C code.
//fast modular exponentiation
int fme(int x, int k, int n)
{
int temp;
int result = 1;
if (k>0)
{
temp = fme(x,k/2,n);
if(k%2==1)
{
result = x % n;
}
//as n<1000 the result of multiplication is less than 2^30
result = (result*temp*temp)%n;
}
return result;
}
Here is the code I have so far in MIPS. In my main method before this code snippet I just ask for an input of values for x
, k
, and n
.
Essentially the code is trying to run the method for fast modular exponentiation. a^k * mod n
. The case when the exponent k
is less than 0
returns 1
correctly, but any other values of k
result in nothing being returned. I can't seem to figure out where I messed up so It would be greatly appreciated if I could have another set of eyes give it a look please and thanks.
I am unsure in my fme
function about the recursion call after doing k/2
if I should store a1 before executing jal? Is that part right? Also I am unsure about the (temp * temp % n)
line of c code if my mips code matches that correctly. Appreciate it greatly
# Call fme function
# place x,k,n into $a0,a1,a2
addi $a0, $s0, 0
addi $a1, $s1, 0
addi $a2, $s2, 0
addi $sp, $sp, -16 #reserve the stack for 4 items, x,k,n, result
sw $ra, 0($sp) #save ra which is going to be the result
sw $a0, 4($sp) #save argument number x
sw $a1, 8($sp) #save argument number k
sw $a2, 12($sp) #save argument number n
jal fme
lw $a2, 12($sp) #restore arg number n
lw $a1, 8($sp) #restore arg number k
lw $a0, 4($sp) #restore arg number x
lw $ra, 0($sp) #restore return address
addi $sp, $sp, 16 #restore sp stack
move $a0, $v0
#print result
li $v0, 1
syscall
########################
# Terminate program
li $v0, 10
syscall
#######################
# fme Function
# x^k mod n
#a0 is x, a1 is k, a2 is n
fme:
slt $t0, $zero, $a1 #check if 0 is less than k.
beq $t0, 0, returnone #if(k<0)then return result as 1
addi $t4, $zero, 2 #placeholder for the number 2
#(k>0)
div $a1, $t4 #divide k by 2
mfhi $t1 #$t1 is remainder of k/2
mflo $a1 #$a1 is quotient of k/2
#temp = fme(x, k/2, n)
jal fme #recursive call with k/2
beq $t1, 1, kmodtwo #if (k%2==1)
#if (k%2 !=1)
#result = (result * temp * temp) % n
# result = (1 * temp * temp) % n
# result = (temp * temp) % n
mult $v0, $v0 #temp * temp
mflo $t2
div $t2, $a2 #(temp*temp) % n
mfhi $v0 #result is in $t3
j fmedone #return call
fmedone: #closes the stack and returns.
lw $ra, 0($sp)
lw $a0, 4($sp)
lw $a1, 8($sp)
lw $a2, 12($sp)
addi $sp, $sp, 16
jr $ra
returnone:
#addi $v0, $v0, 1
li $v0, 1
jr $ra
kmodtwo:
#if (k%2==1)
#result = x % n
div $a0, $a2 #x/n
mfhi $a0 #remainder of x/n which is x%n
add $v0, $a0, $zero
j fmedone