| |||
| Home > Writing ARM Assembly Language > Load and store multiple register instructions > Implementing stacks with LDM and STM | |||
The load and store multiple instructions can update the base register. For stack operations, the base register is usually the stack pointer, sp. This means that you can use these instructions to implement push and pop operations for any number of registers in a single instruction.
The load and store multiple instructions can be used with several types of stack:
The stack grows downwards, starting with a high address and progressing to a lower one (a descending stack), or upwards, starting from a low address and progressing to a higher address (an ascending stack).
The stack pointer can either point to the last item in the stack (a full stack), or the next free space on the stack (an empty stack).
To make it easier for the programmer, stack-oriented suffixes can be used instead of the increment or decrement, and before or after suffixes. Table 2.9 shows the stack-oriented suffixes and their equivalent addressing mode suffixes for load and store instructions.
Table 2.9. Stack-oriented suffixes and equivalent addressing mode suffixes
| Stack-oriented suffix | For store or push instructions | For load or pop instructions |
|---|---|---|
| FD (Full Descending stack) | DB (Decrement Before) | IA (Increment After) |
| FA (Full Ascending stack) | IB (Increment Before) | DA (Decrement After) |
| ED (Empty Descending stack) | DA (Decrement After) | IB (Increment Before) |
| EA (Empty Ascending stack) | IA (Increment After) | DB (Decrement Before) |
Table 2.10 shows the load and store multiple instructions with the stack-oriented suffixes for the various stack types.
Table 2.10. Suffixes for load and store multiple instructions
| Stack type | Store | Load |
|---|---|---|
| Full descending | STMFD (STMDB,
Decrement Before) | LDMFD (LDM,
increment after) |
| Full ascending | STMFA (STMIB,
Increment Before) | LDMFA (LDMDA,
Decrement After) |
| Empty descending | STMED (STMDA,
Decrement After) | LDMED (LDMIB,
Increment Before) |
| Empty ascending | STMEA (STM,
increment after) | LDMEA (LDMDB,
Decrement Before) |
For example:
STMFD sp!, {r0-r5} ; Push onto a Full Descending Stack
LDMFD sp!, {r0-r5} ; Pop from a Full Descending Stack
The Procedure Call Standard for the ARM Architecture (AAPCS), and ARM and Thumb C and C++ compilers always use a full descending stack.
The PUSH and POP instructions assume
a full descending stack. They are the preferred synonyms for STMDB and LDM with
writeback.
Stack operations are very useful at subroutine entry and exit. At the start of a subroutine, any working registers required can be stored on the stack, and at exit they can be popped off again.
In addition, if the link register is pushed onto the stack at entry, additional subroutine calls can be made safely without causing the return address to be lost. If you do this, you can also return from a subroutine by popping pc off the stack at exit, instead of popping lr and then moving that value into pc. For example:
subroutine PUSH {r5-r7,lr} ; Push work registers and lr
; code
BL somewhere_else
; code
POP {r5-r7,pc} ; Pop work registers and pc
Use this with care in mixed ARM and Thumb systems. In ARMv4T
systems, you cannot change state by popping directly into pc. In
these cases you must pop the address into a temporary register and
use the BX instruction.
In ARMv5T and above, you can change state in this way.
See Chapter 5 Interworking ARM and Thumb in the Developer Guide for more information on mixing ARM and Thumb.