Stack frame setup in ARM Architecture - Time & Space Complexity
When a function runs on ARM architecture, it sets up a stack frame to keep track of data like return addresses and local variables.
We want to understand how the time to set up this stack frame changes as the function's needs grow.
Analyze the time complexity of the following ARM code snippet for setting up a stack frame.
push {fp, lr} // Save frame pointer and return address
mov fp, sp // Set frame pointer
sub sp, sp, #16 // Allocate space for locals
// Function body ...
add sp, sp, #16 // Deallocate locals
pop {fp, pc} // Restore frame pointer and return
This code saves important registers, sets up space for local variables, and restores everything before returning.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Fixed number of push, pop, add, and sub instructions for stack setup and teardown.
- How many times: Each instruction runs once per function call; no loops or recursion in setup.
The number of instructions to set up the stack frame stays the same regardless of input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 instructions |
| 100 | 5 instructions |
| 1000 | 5 instructions |
Pattern observation: The setup cost does not grow with input size; it remains constant.
Time Complexity: O(1)
This means the time to set up the stack frame stays the same no matter how big the input is.
[X] Wrong: "Stack frame setup time grows with the size of input data or number of local variables."
[OK] Correct: The setup instructions run a fixed number of times; space for locals is reserved by adjusting the stack pointer, which is a single instruction regardless of size.
Understanding stack frame setup time helps you appreciate how function calls work efficiently at a low level, a useful skill when discussing performance or debugging.
"What if the function had to save many more registers or allocate a very large local array? How would the time complexity of stack frame setup change?"
Practice
Solution
Step 1: Understand stack frame role
A stack frame stores important data like return address and local variables for each function call.Step 2: Identify the main purpose
This setup ensures the function can return correctly and use local data safely.Final Answer:
To save the return address and local variables safely -> Option AQuick Check:
Stack frame purpose = Save return address and locals [OK]
- Confusing stack frame with CPU speed control
- Thinking it clears all registers
- Mixing local and global variable storage
Solution
Step 1: Identify instruction to save LR
The link register (LR) holds the return address and is saved on the stack using PUSH.Step 2: Match correct instruction
PUSH {LR} stores LR on the stack; POP {LR} restores it. MOV and ADD do not save LR on stack.Final Answer:
PUSH {LR} -> Option CQuick Check:
Save LR with PUSH {LR} [OK]
- Using POP instead of PUSH to save
- Confusing MOV with stack operations
- Adding to SP instead of saving LR
SUB SP, SP, #16
PUSH {LR}
What is the effect on the stack pointer (SP) after these instructions?Solution
Step 1: Analyze SUB SP, SP, #16
This subtracts 16 from SP, moving it down by 16 bytes to allocate space.Step 2: Analyze PUSH {LR}
PUSH stores LR on stack, which decreases SP by 4 bytes (ARM uses 4-byte words).Final Answer:
SP decreases by 16 bytes, then by 4 bytes -> Option BQuick Check:
SP moves down 16 + 4 bytes = 20 bytes total [OK]
- Adding to SP instead of subtracting
- Ignoring PUSH effect on SP
- Assuming SP stays same after PUSH
SUB SP, SP, #8
POP {LR}
Solution
Step 1: Understand stack frame setup order
Function prologue saves LR by PUSH before changing SP to allocate space.Step 2: Identify incorrect instruction
POP removes data from stack; here it tries to restore LR before saving it, which is wrong.Final Answer:
POP should be PUSH to save LR first -> Option DQuick Check:
Save LR with PUSH before POP [OK]
- Using POP instead of PUSH to save LR
- Changing SP incorrectly
- Ignoring function prologue conventions
Solution
Step 1: Save LR before allocating locals
Correct order is to allocate space first by subtracting from SP, then save LR with PUSH.Step 2: Check options for correct order and size
SUB SP, SP, #24 PUSH {LR} subtracts 24 bytes first, then saves LR, which is the correct order to allocate space and save registers.Step 3: Re-examine options carefully
SUB SP, SP, #24 PUSH {LR}: SUB SP, SP, #24 then PUSH {LR} - correct order and size.
PUSH {LR} SUB SP, SP, #24: PUSH {LR} then SUB SP, SP, #24 - wrong order.
PUSH {LR, R4} SUB SP, SP, #20: PUSH {LR, R4} then SUB SP, SP, #20 - wrong registers and size.
SUB SP, SP, #28 PUSH {LR}: SUB SP, SP, #28 then PUSH {LR} - wrong size.Final Answer:
SUB SP, SP, #24 PUSH {LR} -> Option AQuick Check:
Allocate locals first, then save LR [OK]
- Allocating space after saving LR
- Using wrong register sets in PUSH
- Mismatching allocated bytes and saved registers
Ready to prove it?
Pass the test and this pattern moves unknown
