2.8.3. 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:

Descending or ascending

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).

Full or empty

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. Refer to Table 2.5 for a list of stack-oriented suffixes.

Table 2.5. Suffixes for load and store multiple instructions

Stack typePushPop
Full descendingSTMFD (STMDB)LDMFD (LDMIA)
Full ascendingSTMFA (STMIB)LDMFA (LDMDA)
Empty descendingSTMED (STMDA)LDMED (LDMIB)
Empty ascendingSTMEA (STMIA)LDMEA (LDMDB)

For example:

    STMFD    r13!, {r0-r5}  ; Push onto a Full Descending Stack
    LDMFD    r13!, {r0-r5}  ; Pop from a Full Descending Stack.

Note

The ARM-Thumb Procedure Call Standard (ATPCS), and ARM and Thumb C and C++ compilers always use a full descending stack.

Stacking registers for nested subroutines

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. If you do this, you can also return from a subroutine by popping the pc off the stack at exit, instead of 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

Note

Use this with care in mixed ARM and Thumb systems. In ARM architecture v4T systems, you cannot change state by popping directly into the program counter.

In ARM architecture v5T and above, you can change state in this way.

See the Interworking ARM and Thumb chapter in ADS Developer Guide for further information on mixing ARM and Thumb.

Copyright © 2000, 2001 ARM Limited. All rights reserved.ARM DUI 0068B
Non-Confidential