Fibonacci walkthrough

Consider the following code:

/* Return the nth Fibonacci number */
int fib(int n) {
    int fibn;
    int fibn1;
    fib2(n, &fibn, &fibn1);
    return fibn;
}

/* Return the nth Fibonacci number in pfibn and the (n-1)th in pfibn1. */
void fib2(int n, int *pfibn, int *pfibn1) {
    if (n <= 1) {
        *pfibn = 1;
        *pfibn1 = 1;
    }
    else {
        int fibn2;
        fib2(n-1, pfibn1, &fibn2);
        *pfibn = *pfibn1 + fibn2;
    }
}

Let's step through a call to fib(3). The call creates an activation record, containing space for the parameter n and for the local variables fibn and fibn1. A value of ? indicates that the variable is uninitialized.

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?

This invokes fib2, creating an activation record, or stack frame for fib2 with space for its parameters as well as itn local variable fibn2. The call stack now looks like:

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 ?

fib2 invokes fib2 recursively. The call stack now looks like:

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 ?
fib2(2, 0x1008, 0x101c)
0x1020 n 2
0x1024 pfibn 0x1008
0x1028 pfibn1 0x101c
0x102c fibn2 ?

After one more recursive call, the call stack now looks like:

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 ?
fib2(2, 0x1008, 0x101c)
0x1020 n 2
0x1024 pfibn 0x1008
0x1028 pfibn1 0x101c
0x102c fibn2 ?
fib2(1, 0x101c, 0x102c)
0x1030 n 2
0x1034 pfibn 0x101c
0x1038 pfibn1 0x102c
0x103c fibn2 ?

The function writes 1 into the pointers passed in.

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 1
fib2(2, 0x1008, 0x101c)
0x1020 n 2
0x1024 pfibn 0x1008
0x1028 pfibn1 0x101c
0x102c fibn2 1
fib2(1, 0x101c, 0x102c)
0x1030 n 2
0x1034 pfibn 0x101c
0x1038 pfibn1 0x102c
0x103c fibn2 ?

The function then returns, popping the activation record:

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 ?
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 1
fib2(2, 0x1008, 0x101c)
0x1020 n 2
0x1024 pfibn 0x1008
0x1028 pfibn1 0x101c
0x102c fibn2 1

The returned values are then added, writing 2 into the fib(3) activation record.

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 2
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 1
fib2(2, 0x1008, 0x101c)
0x1020 n 2
0x1024 pfibn 0x1008
0x1028 pfibn1 0x101c
0x102c fibn2 1

The function then returns, popping the activation record.

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn ?
0x1008 fibn1 2
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 1

The sum 3 is computed and stored at the address passed in (0x1004).

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn 3
0x1008 fibn1 2
fib2(3, 0x1004, 0x1008)
0x1010 n 3
0x1014 pfibn 0x1004
0x1018 pfibn1 0x1008
0x101c fibn2 1

fib2 then returns for the last time. The value stored in fibn is returned to the caller.

Address Variable Value
fib(3)
0x1000 n 3
0x1004 fibn 3
0x1008 fibn1 2