| |||
| Home > Basic Assembly Language Programming > 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, r13. This means that you can use load and store multiple 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).
In practice stacks are almost always full, descending. The C compilers produce full, descending stacks.
To make it easier for the programmer, stack oriented suffixes can be used instead of the Increment/Decrement and Before/After suffixes. See Table 5.6 for a list of stack oriented suffixes.
Table 5.6. Suffixes for load and store multiple instructions
| Stack type | Push | Pop |
|---|---|---|
| Full Descending | STMFD (DB) | LDMFD (IA) |
| Full Ascending | STMFA (IB) | LDMFA (DA) |
| Empty Descending | STMED (DA) | LDMED (IB) |
| Empty Ascending | STMEA (IA) | LDMEA (DB) |
For example:
STMFD r13!, {r0-r5} ; Push onto a Full Descending Stack.
LDMFD r13!, {r0-r5} ; Pop from a Full Descending Stack.
STMFA r13!, {r0-r5} ; Push onto a Full Ascending Stack.
LDMFA r13!, {r0-r5} ; Pop from a Full Ascending Stack.
STMED r13!, {r0-r5} ; Push onto Empty Descending Stack.
LDMED r13!, {r0-r5} ; Pop from Empty Descending Stack.
STMEA r13!, {r0-r5} ; Push onto Empty Ascending Stack.
LDMEA r13!, {r0-r5} ; Pop from Empty Ascending Stack.
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 safely be made without causing the return address to be lost. You can return from a subroutine by popping the pc off the stack at exit, rather than by popping lr and then moving that value into the pc.
For example:
subroutine STMFD sp!, {r5-r7,lr} ; Push work registers and lr
; code
BL somewhere_else
; code
LDMFD sp!, {r5-r7,pc} ; Pop work registers and pc
Use this with care in mixed ARM/Thumb systems. You cannot return to Thumb code by popping directly into the program counter.