131 Week 15 - ARM Functions Flashcards
Function
A stored subroutine that performs a specific task based on the parameters with which it is provided.
Branching to a label is not a function, specific rules need to be followed to implement a function.
Uses of functions
- Complex operations can be performed by calling a procedure.
- Make code easier to understand and manage.
- Program elements that can easily be re-used.
- Same procedure can be called many times within a program.
Function execution
- Caller stores arguments in registers or memory
- Function call: Caller transfers flow control to the callee
- Callee acquires/allocates memory for doing work
- Callee executes the function body
- Callee stores the result in “some” register
- Callee deallocates memory
- Function return: Callee returns control the caller
branch and link
syntax: bl ProcedureAddress
bl stores the address of the next instruction in register lr (link register) then jumps to procedure address.
To return after function execution has finished, store the address in lr to pc.
This can be done by ending a function with bx lr.
Calling conventions
Implementation of a function should follow a set of calling conventions to ensure interoperability.
By using conventions functions written by different programmers or compiled using different compilers can still interoperate.
Conventions also allow you to use library functions without corrupting state.
Convention 1 - registers for procedure calls
r0-r3 are used as argument registers where parameters can be passed to the function.
r0 is used to return a value from the function.
lr is used as a return address register.
Convention 2 - preserving registers.
If the function modifies the values of registers r4-r11, the stack pointer (SP/r13) or return address (LR/r14) it must preserve them after it has finished.
Temporary register (r12), argument registers (r0-r3) and CPSR are not preserved.
Convention 3 - Using the stack to preserver registers
Registers are conventionally preserved by pushing the registers to the stack [PUSH {R4, LR}] then popping them from the stack at the end of the function [POP {R4, PC}].
Using PUSH {LR} and POP {PC} allows LR to be preserved during function execution and then moved to PC after execution has finished. It removes the need for the bx lr line.
Register spilling
Moving the contents of registers to main memory.
Procedure nesting
If procedures are nested we must always preserve lr to the stack to save the return address for each function.
Stack
Stack grows downwards.
Stack pointer (SP) always points to the top of the stack. Because the stack grows downwards, when we push an item to the stack, the stack pointer address will decrease.