Factorial function in Java:
public class Fac
{
public static int fac(int n)
{
if (n == 0)
return(1); <--- base case
else
{
return( n * fac(n-1) ); <--- recursive case
}
}
static int result, k=4;
public static void main( )
{
result = fac(k);
}
}
|
You already learned how to code a recursive function !
The main( ) function must pass the parameter k (fac(k)) using the runtime stack:
main:
/* -------------------------------------------------
Pass parameter k (using stack)
------------------------------------------------- */
movw r0, #:lower16:k
movt r0, #:upper16:k
ldr r0, [r0] // r0 = k
push {r0} // Pass k using the program stack
/* ------------------------------------------------------
call fac(k)
------------------------------------------------------ */
bl fac
add sp, sp, #4 // Clean up the parameter k from the stack
/* -----------------------------------------------------------------
Assign return value (in r0) to variable result
----------------------------------------------------------------- */
movw r1, #:lower16:result // Do NOT use r0 !!!
movt r1, #:upper16:result // (Because r0 contains the return value)
str r0, [r1] // This will store return value in result
|
The fac(int n) function has 1 parameter (n) and no local variables
Therefore, the stack frame structure created (and used by fac( )) is as follows:
Stack frame of the fac( ) method:
SP
FP -----> +---------------------+
0 | old Frame Pointer | (4 bytes)
+---------------------+
4 | Return Address | (4 bytes)
+---------------------+
8 | Parameter n | addr(n) = FP + 8
+---------------------+
|
You just pass n-1 as parameter and call the factorial function using bl fac:
fac:
/* ==========================================================
Function Prelude: complete the stack frame structure
========================================================== */
push {lr} // Save LR (return address)
push {fp} // Save FP (used by caller)
mov fp, sp // Mark the stack top location before
// allocating any local variables
sub sp, sp, #0 // Allocate 0 int variables on the stack
// (I could omit this instruction....)
/* ===============================================
Now we can write the function body
=============================================== */
// if ( n == 0 )
ldr r0, [fp, #8] // r0 = n
cmp r0, #0 // Check n == 0
bne else // n != 0 --> Goto "else" part
// return 1
///// put return value 1 in return location r0
mov r0, #1
/* =============================================================
Function Postlude: de-allocate local variable and restore FP
============================================================= */
mov sp, fp // De-allocate local variables
pop {fp} // Restore fp
pop {pc} // Return to the caller
else:
// Compute: n*fac(n-1)
//// Compute fac(n-1) first
ldr r0, [fp, #8] // r0 = n
sub r0, r0, #1 // r0 = n-1
push {r0} // pass (n-1) to fac on stack
bl fac // Calls: fac( ) with parameter = (n-1) !!!
add sp, sp, #4 // Clean up parameter (n-1) from stack
//// ** Right here and now: r0 = fac(n-1) !!!
//// Compute n*fac(n-1) next
ldr r1, [fp, #8] // r0 = n
mul r0, r1, r0 // r0 = n*fac(n-1)
// NOTE: r0 has the correct return value !!!
// return - with n*fac(n-1) inside r0 !!!
/* =============================================================
Function Postlude: de-allocate local variable and restore FP
============================================================= */
mov sp, fp // De-allocate local variables
pop {fp} // Restore fp
pop {pc} // Return to the caller
|