86 lines
1.3 KiB
Markdown
86 lines
1.3 KiB
Markdown
# ARM Subroutines
|
|
|
|
Subroutine, Function, Procedure
|
|
|
|
It has a single-entry and single-exit.
|
|
|
|
* `bl lbl`
|
|
* set `lr` to the next instruction location
|
|
* set `pc` to the label
|
|
* `bx lr`
|
|
* set `pc` to the saved `lr`
|
|
|
|
ARM register calling convention:
|
|
|
|
|
|
|
|
Passing Argument via registers:
|
|
|
|
```armasm
|
|
mov r0, #3
|
|
mov r1, #4
|
|
bl ssq
|
|
mov r2, r0
|
|
b endl
|
|
SSQ:
|
|
mul r0, r0, r0
|
|
mul r1, r1, r1
|
|
add r0, r0, r1
|
|
bx lr
|
|
```
|
|
|
|
`pc` **is always incremented by 4**. Each time, 4 bytes are fetched from the instruction memory. It is not depending on instruction size (2 or 4 bytes).
|
|
|
|
|
|
## Using Stack
|
|
|
|
Stack is a LIFO data structure.
|
|
* `push` / `pop`
|
|
|
|
There is two stack growth convention:
|
|
* Ascending and Descending.
|
|
* Full and Empty
|
|
|
|
`sp` = `r13`
|
|
Coretex-M uses **Full Descending stack**.
|
|
|
|
commands
|
|
* `push {register_list}`
|
|
* `stmdb sp!, {register_list}`
|
|
* `pop {register_list}`
|
|
* `ldmia sp!, {register_list}`
|
|
|
|
**`push` instruction**
|
|
|
|
`push {Rd}`
|
|
|
|
**`pop` instruction**
|
|
|
|
|
|
### multi-level subroutines
|
|
|
|
```armasm
|
|
main:
|
|
mov r0, #2
|
|
bl quad
|
|
quad:
|
|
push { lr }
|
|
bl sq
|
|
bl sq
|
|
pop { lr }
|
|
bx lr
|
|
sq:
|
|
mul r0, r0
|
|
bx lr
|
|
```
|
|
|
|
## Initializing SP
|
|
|
|
Before using the stack, software has to define stack pointer
|
|
|
|
|
|
## Recursive Function
|
|
|
|
No difference to multi-level subroutines.
|
|
|
|
It has multiple stack frames. |