The stack pointer (SP) and link register (LR) are important registers used for function calls and returns in ARM processors. The SP points to the top of the stack, while the LR stores the return address when a function call is made.
Stack Pointer (SP)
The stack is a region of memory used for temporary data storage during function calls. It works on the principle of Last In First Out (LIFO) – the last item pushed onto the stack is the first one to be popped out.
The SP register points to the top of the stack. It indicates where the next data should be pushed to or popped from. Some key points about SP:
- SP holds the memory address of the top of the stack.
- When a push operation occurs, SP is decremented by the data size and the data is written to the new top of stack address.
- For a pop operation, SP is incremented after data is read from the stack top.
- SP is manipulated automatically by push and pop instructions.
- The stack grows downwards towards lower memory addresses.
- SP alignment is maintained – SP will be adjusted to point to a valid memory boundary after pushes/pops.
The stack allows for local variables and function parameters to be allocated temporarily during execution. It provides a swift and efficient method to pass data between functions.
Link Register (LR)
The LR register contains the return address when a function call occurs. When one function calls another, the LR is used in the following way:
- The current value of the PC (program counter) is copied into the LR.
- The PC is updated to jump to the start of the called function.
- On function return, the saved LR is copied back into the PC.
This allows execution to continue at the original calling address after the callee function completes. Some key points about LR:
- LR holds the address of the next instruction after the CALL.
- LR is automatically saved/restored during function calls.
- Programmers can manually modify LR for changes in control flow.
- Some ARM processor modes have banked LR registers for interrupts.
- Inline assembly or intrinsics may be needed to directly access LR.
Stack and Link Register Usage
Here is a typical high-level view of SP and LR usage during function calls:
- Main() calls FuncA().
- LR gets Main() PC return address.
- SP allocates stack space for FuncA().
- FuncA() calls FuncB().
- LR gets FuncA() PC return address.
- SP allocates stack space for FuncB().
- FuncB() finishes and returns to FuncA().
- SP deallocates FuncB() stack space.
- LR restores FuncA() return address.
- FuncA() finishes and returns to Main().
- SP deallocates FuncA() stack space.
- LR restores Main() return address.
The stack pointer handles allocation of temporary stack space for each function’s local data. The link register handles tracking the correct return address through multiple layers of function calls.
ARM Hardware Support
The SP and LR registers are supported directly in ARM processors and can be accessed using various instructions:
- PUSH/POP – Push and pop data to/from stack using SP.
- STM/LDM – Store/load multiple registers to/from stack.
- BL/BLX – Branch with link to store return address in LR.
- BX – Branch exchange to return using LR.
- MOV – Move values between LR and other registers.
The Program Status Register (PSR) is also important for tracking the Arm/Thumb processor state during function calls.
Different ARM architectures may have varying stack alignment rules and PSR requirements. The Application Procedure Call Standard (APCS) defines common conventions to follow for compliant ABI behavior.
Compiler Handling
High level languages like C/C++ rely on the compiler to handle SP and LR management during function calls:
- Compilers automatically issue PUSH/POP instructions for register saving/restoring in prologues/epilogues.
- Frame Pointer (FP) register may be used to provide additional stack management relative to SP location.
- LR register handling is abstracted, compilers issue BL instructions for calls.
- Compiler generated assembly code handles stack allocation/deallocation.
- Compilers utilize software conventions like callee vs caller saved registers.
Therefore, in normal application code, direct manipulation of SP and LR is not required. However, it is useful to understand the underlying implementation details.
Manual Assembly Usage
SP and LR can be directly accessed in ARM assembly language: PUSH {R0-R3, LR} // Push registers onto stack BL func // Call function saving LR POP {R0-R3, LR} // Restore original registers BX LR // Return using saved LR
Some points for manual SP/LR handling:
- Save/restore any registers needed across function calls.
- Use STM/LDM for saving/restoring multiple registers.
- Adjust SP offset with PUSH/POP or ADD/SUB instructions.
- Use BL/BX instructions for LR function call handling.
- May need to directly modify LR for changes in program flow.
Manual use of stack and link register provides precise control over function prologues and epilogues.
Exception Handling
SP and LR play an important role in ARM exception handling:
- Exception causes stack of registers and LR to be automatically saved.
- SP is used to manage the exception mode stack frame.
- LR contains the address to return to after exception processing.
- Handler code can access SP and LR to view context.
Some common examples include:
- IRQ – Stack used for context saving, return address indicates interrupted code.
- Undefined instruction – LR indicates faulting instruction location.
- Memory fault – SP/LR can identify bad memory access.
Exceptions are a complex area but SP and LR provide the foundation for robust exception handling in ARM systems.
Operating System Usage
SP and LR enable critical OS capabilities:
- Multitasking – OS saves SP/LR during context switches.
- Interrupts – IRQ handler uses SP/LR for context storage.
- System calls – Transition to kernel mode using BL instruction.
- Thread management – Separate stack pointer for each thread.
Additional OS features like virtual memory may also utilize the stack pointer for managing address translations.
Summary
In summary, the stack pointer and link register provide fundamental stack management and subroutine linkage support in ARM processors. Mastering SP and LR is key to harnessing the full power of the ARM architecture for efficient function calls, interrupt handling, and operating system development.