Activation Records and Function Calls: Stack Frames, Worked Trace and Exam Traps

Build a reliable stack-frame model with exact call, return, recursion and nested-procedure traces, plus a fully mapped 72-byte teaching layout.

KnowledgeGate Team

Exam prep & CS education

Updated 20 Sep 20266 min read

Students can often list parameters, local variables and a return address, yet still mix up an activation with its record, assume one function means one frame, or follow the wrong link in a nested call. A call-to-return model follows main -> f(3) -> g(5,3), with a 72-byte frame calculation and four recursive frames. The byte layout is an explicit teaching convention because real compilers and ABIs may use registers or arrange fields differently.

Related reading: activation record MCQs and recursion stacks.

Activation records and stack frames: the exact distinction

An activation is one execution of a function. Its activation record, or stack frame, holds that execution's runtime data. Recursion creates one record per call although every call runs the same compiled body.

Common fields are parameters, a return-value location, return address, dynamic link or saved caller FP, optional static link, saved registers, locals and temporaries. Parameters carry inputs; temporaries hold compiler-generated values during execution. Not every language or ABI stacks every field, and order is not universal.

Code and state are different. One copy of f can have frames for f(4), f(3) and f(2), each with its own parameter and return point. Use the GATE CS Exam Preparation Courses and Test Series catalog and Compiler Design map for context.

What a call sequence and return sequence actually do

Assume a simplified downward-growing stack. SP marks its top; FP gives fields a stable reference while SP moves. The caller evaluates arguments and records where execution continues. The callee preserves state, establishes its frame, allocates locals and starts the body.

  1. The caller computes arguments.

  2. Control transfers with a return address.

  3. The callee saves the caller's frame reference and registers.

  4. It allocates locals and executes.

  5. It places the result in its agreed location.

  6. Its epilogue releases locals, restores state and uses the return address.

A return address names an instruction such as main:after_f; a dynamic link identifies the caller's record. One restores control flow, the other frame state. LIFO means the newest active frame normally finishes first, which is why calls and recursion fit a stack.

Worked call trace: main -> f(3) -> g(5,3)

Code
g(a, b):
    t = a * b
    return t - 1

f(x):
    y = x + 2
    return g(y, x)

main:
    ans = f(3)

event

top frame

older active frames

computed value

Enter f

f: x=3, y=unassigned, RA=main:after_f, DL=main

main: ans=unassigned

x=3

Set y

f: x=3, y=5

main

3+2=5

Enter g

g: a=5, b=3, t=unassigned, RA=f:after_g, DL=f

f: x=3, y=5; main

(a,b)=(5,3)

Set t

g: a=5, b=3, t=15

f; main

5*3=15

Pop g

f: x=3, y=5

main

15-1=14

Pop f

main: ans=unassigned

none

return 14

Resume main

main: ans=14

none

ans=14

Pop only g. Suspended f resumes at f:after_g, receives and returns 14, then is popped. main resumes at main:after_f and stores ans=14.

While g runs, stack order from top is g, f, main. Then it is f, main, and finally main. The frames preserve f's x=3, y=5 while g uses separate values.

Three stack snapshots of main calling f(3) then g(5,3), with frames pushed and popped as g returns 14 to main.

Worked frame-size and address calculation

Take an illustrative 64-bit, stack-passed convention. Immediately before the callee frame is built, SP=0x1000, and the stack grows towards lower addresses. Allocate two 8-byte parameters (16 bytes), an 8-byte return address, an 8-byte dynamic link or saved FP, two saved 8-byte registers (16 bytes), a local area rounded to 16 bytes, and one 8-byte temporary area.

Calculate every term:

Code
16 + 8 + 8 + 16 + 16 + 8 = 72 bytes = 0x48 bytes
new SP = 0x1000 - 0x48 = 0x0FB8
FP = 0x0FE0

From low to high:

field

inclusive address range

temporary

0x0FB8-0x0FBF

locals

0x0FC0-0x0FCF

saved registers

0x0FD0-0x0FDF

dynamic link

0x0FE0-0x0FE7

return address

0x0FE8-0x0FEF

parameter a

0x0FF0-0x0FF7

parameter b

0x0FF8-0x0FFF

As a cross-check, a starts at FP+16 because 0x0FE0+0x10=0x0FF0. Parameter b starts at FP+24 because 0x0FE0+0x18=0x0FF8. The 72-byte result and these offsets are correct only for this stated teaching convention, not for a named real ISA or ABI.

Recursion means many records for one function

Activation records sit inside a broader run-time model of memory regions, allocation, displays and parameter passing, developed in Run-Time Environment in Compiler Design. Frame construction, address arithmetic, call order and return state need a closer trace. With n <= 1 as the base condition, fact(4) creates four records; the linked run-time-environment example uses n == 0, so its same-named call creates five.

Define fact(n) = 1 when n <= 1; otherwise, fact(n) = n * fact(n-1). Calling fact(4) creates four simultaneously active fact records with parameter values 4, 3, 2 and 1. Each non-base call waits at its own multiplication.

The unwind keeps those values separate:

Code
fact(1) = 1
fact(2) = 2 * 1 = 2
fact(3) = 3 * 2 = 6
fact(4) = 4 * 6 = 24

One shared local n would fail because the waiting calls still need their distinct values 4, 3 and 2. If this teaching model assigns 32 bytes to each fact frame, four frames require 4*32=128 bytes. If a separate main frame uses 16 bytes, total active stack storage at the deepest point is 128+16=144 bytes.

Do not report the depth as three. The base-case call fact(1) is a real activation and has its own record, so the four parameter values prove that the recursion depth here is four.

In an explicitly lexically scoped teaching language, P has x=10. Inside P, Q defines siblings R and S. R returns x+1. S(k) declares local x=99 and invokes procedure argument k. Then Q calls S(R), so S invokes R while active.

When R runs, the dynamic call chain is R -> S -> Q -> P, which answers who called whom. Its static or lexical chain is R -> Q -> P because Q, not S, is R's lexical parent.

Resolve x lexically: R has no local x; neither does Q; P supplies x=10. Therefore R returns 10+1=11, not 100. It cannot use S's x=99 because S is a dynamic caller, not a lexical ancestor.

Static links are one technique for non-local access. Displays or closure environments can enforce the same rule, so a literal static-link field is not universal.

Frames P, Q, S and R with the dynamic chain R to S to Q to P versus the static chain R to Q to P; x resolves to 10 so R returns 11.

Exam-style checks and the traps that change the answer

Questions ask you to identify fields, distinguish links, count records, calculate SP, or trace calls.

Use these rapid checks:

  1. At the deepest point of main -> A -> B -> C, there are 4 active records, including main.

  2. Six recursive calls at 40 bytes each require 6*40=240 bytes for those recursive frames.

  3. With downward growth, SP=4096 and a 48-byte frame give SP=4096-48=4048.

  4. A link to the lexical parent is static; a link to the runtime caller is dynamic.

Repair traps. One function is not one frame, so count calls. Frame size is not just locals, so include every field and padding. A return address is not a frame pointer, so separate code and frame locations. Dynamic order is not lexical scope, so follow the required link.

The KnowledgeGate practice bank currently has more than 20 activation-record questions for applying these checks.

The short version and the next practice step

Use a five-step solver: write the call order; draw one frame per active call; fill parameters and locals; label return, dynamic and any static links separately; then pop in reverse order while carrying each result back.

Remember the anchors: g(5,3) returns 14; the 72-byte frame moves SP from 0x1000 to 0x0FB8; fact(4) creates four frames and returns 24; nested R follows its static chain to P.x=10 and returns 11.

Now redraw the three stack snapshots and four recursion frames without looking. For optional structured study, use GATE Guidance by Sanchit Sir, then use the GATE Test Series for broader practice.