Consider the following recursive function with local variables:
public class Recurse
{
public static int f(int a, int b)
{
int i, s;
s = 0;
for (i = a; i < b; i++)
{
s = s + f(a+1, b-1) + 1;
}
return s;
}
public static void main( )
{
int result = f(2, 5);
}
}
|
DEMO: /home/cs255001/demo/asm/8-sub/recurse.s
The main( ) function must pass the parameters (f(2,5)) using the runtime stack:
main:
/* -------------------------------------------------
Pass parameters (using stack)
------------------------------------------------- */
mov r0, #5
push {r0} // Pass 5 (param 2) using the program stack
mov r0, #2
push {r0} // Pass 2 (param 1) using the program stack
/* ------------------------------------------------------
call f(2,5)
------------------------------------------------------ */
bl f
add sp, sp, #8 // Clean up the parameters 2,5 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 f(int a, int b) function has 2 parameter (a, b) and 2 local variables (i, s)
Therefore, the stack frame structure created (and used by f( )) is as follows:
Stack frame of the f( ) method:
SP -----> +---------------------+
-8 | Local var i | addr(i) = FP - 8
+---------------------+
-4 | Local var s | addr(s) = FP - 4
FP -----> +---------------------+
0 | old Frame Pointer | (4 bytes)
+---------------------+
4 | Return Address | (4 bytes)
+---------------------+
8 | Parameter a | addr(a) = FP + 8
+---------------------+
12 | Parameter b | addr(b) = FP + 12
+---------------------+
|
f:
// When f begins, we will have: a,b on the stack
/* ==========================================================
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, #8 // Allocate 2 int variables on the stack
/* ===============================================
We completed the stack frame
Now we can write the function body
=============================================== */
// s = 0
mov r0, #0
str r0, [fp, #-4] // assign 0 to s
// i = a
ldr r0, [fp, #8] // r0 = a
str r0, [fp, #-8] // assign to i
while:
// while ( i < b )
ldr r0, [fp, #-8] // r0 = i
ldr r1, [fp, #12] // r1 = b
cmp r0, r1 // i ? b
bge whileEnd // Exit for loop
// We CANNOT compute s + f(a+1, b-1) + 1 without the
// value (= a number) for: f(a+1, b-1)
// Compute f(a+1, b-1) first !
ldr r0, [fp, #12] // r0 = b
sub r0, r0, #1 // r0 = b-1
push {r0} // pass param2 (b-1)
ldr r0, [fp, #8] // r0 = a
add r0, r0, #1 // r0 = a+1
push {r0} // pass param1 (a+1) to f on stack
bl f
add sp, sp, #8 // Clean up parameter (n-1) from stack
// We can now compute s + f(a+1, b-1) + 1
ldr r1, [fp, #-4] // r1 = s
add r0, r0, r1 // r0 = s + f(a+1, b-1)
add r0, r0, #1 // r0 = s + f(a+1, b-1) + 1
str r0, [fp, #-4] // Assign s + f(a+1, b-1) + 1 to s
// i++
ldr r0, [fp, #-8] // r0 = i
add r0, r0, #1 // r0 = i + 1
str r0, [fp, #-8] // Assign i+1 to i
b while
whileEnd:
// return s in r0
ldr r0, [fp, #-4] // r0 = s
/* =============================================================
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
|
DEMO: /home/cs255001/demo/asm/8-sub/recurse.s