Vous êtes sur la page 1sur 4

ARM stacks Stacks on ARM processors The stack may be accessed in several ways; Empty Descending (ED), Empty

Ascending (EA), Full Descending (FD) and Full Ascending (FA). The way the stack pointer changes and the item it points to on the stack will be slightly different in each case. As diagrams these four different ways of accessing the stack are shown below.

Stack

Low

Stack

Low

-8 -4 0 SP Empty posn.
Last stacked

Descending

-12 -8 SP Full posn -4 0


Last stacked

Descending

High Empty Descending

High Full Descending

Empty Descending (ED) Push: put value on stack then decrement sp post-decrement, e.g. stmed. Pop: increment sp then copy item from stack pre-increment, e.g. ldmed. Stack Stack Low Low Full descending (FD) The System Default! SP Last stacked Last stacked 0 stmfd. Push: decrement sp then put item on stack pre-decrement, e.g. Full SP 0 +4 Pop: copy item from stack then increment sp post-increment, e.g. ldmfd. +4 Empty +8 +8 Ascending Ascending

High Empty Ascending Full Ascending

High

Empty Ascending (EA) Push: put item on stack then increment sp post-increment, e.g. stmea. Pop: decrement sp then copy item from stack, e.g. ldmea. Full Ascending (FA) Page 1 of 4 Push: increment sp then put item on stack, e.g. stmfa. Pop: copy item from stack then decrement sp post-decrement, e.g. ldmfa.

ARM stacks

The push and pop operations are store many and load many op codes, the assumption being that a function will need to save and restore the contents of several registers that it is likely to corrupt (of course it is possible to deal with just one register!). When a list of registers is given the lowest numbered register uses the lowest stack memory location and the highest numbered register uses the highest stack memory location. This is true no matter what order we specify the registers! The important thing is to remember whether the stack pointer is altered pre- or post- before the multiple registers are dealt with! e.g.
stmfd sp!, {fp,ip,lr,pc} @ full descending so pre@ decrement sp then copy pc, @ lr, ip, fp to stack, @ leaving sp pointing to the @ stacked fp value @ pre-decrment sp, copy r5 to stack, @ leaving sp pointing to stacked r5 value

stmfd ldmea ldmfd

sp!, {r5}

fp, {fp,sp,lr} sp!, {r5}

@ empty ascending so pre-decrement sp @ then copy fp, sp and lr from stack @ Note no exclamation mark (!) @ copy item from stack then increment sp @ leaving sp pointing to the original item

Use of the stack in ARM C/Assembler programming.

Page 2 of 4

ARM stacks

Assume a C function calls an assembler routine with four parameters. These will be passed in registers r0 to r3. If the routine uses other registers, such as r4, these must be stacked before being used and retrieved after use before the routine returns to the calling function. Assume also that the function has two local variables. These must be catered for on the stack within the functions stack frame. Remember that the default use of the stack is Full Descending, so the stack pointer will point to the last item stacked by the calling function. The assembler function might begin and end as follows:
start: mov stmfd sub sub ip, sp @ basically save the current sp sp!, {fp,ip,lr,pc} @ save important regs. fp, ip, #4 @ initialize the frame pointer sp, sp, #8 @ allow stack space for 2 local vars @ stack regs we corrupt (note we!)

strmfd sp!, {r6,r4,r5}

@ do the rather important work ldmfd sp!, {r5,r6,r4} end: ldmea fp, {fp,sp,pc} @ retrieve values for corrupted regs @ reset fp and sp, jump to return addr

Note that the ARM assembler performs sequential (many) transfers in increasing memory address order i.e. from low to high addresses, so decrementing transfers actually decrement the base register (e.g. fp) first then increment it to get the correct register position in the sequence!

How do the multiple store and load instructions work? The single store multiple instruction: stmfd sp!, {fp, ip, lr, pc} pc, lr, ip, fp, [sp, [sp, [sp, [sp, #-4]! #-4]! #-4]! #-4]!

Can be replaced by these four instructions: str str str str

The stmfd (store multiple, full descending) instruction stores the registers listed between braces { and } (in this case, FP, IP, LR and PC) to memory pointed to by the first operand, called the base register (in this case, SP). The ! indicates the base register is modified at the end of storing all of the registers. The easiest way to understand all this is to look at what the instruction does:

Page 3 of 4

ARM stacks

1. Subtract 4 number of registers listed from the base register. In this case, SP = SP 44. 2. Store the listed registers to memory in ascending order: the lowest-numbered register is stored at the address pointed to by the base register (using its new value), the next-lowestnumbered register at the next word in memory, and so on. Note that listing the registers in a different order will have no effect! In this case, the base register is SP. Hence, register FP (R11) is stored at [SP], register IP (R12) at [SP + 4], register LR (R14) at [SP + 8] and register PC (R15) at [SP + 12]. The single load multiple instruction: Can be replaced by: ldmea fp, {fp, sp, pc} mov ldr ldr ldr ip, fp, sp, pc, fp [ip, #-12] [ip, #-8] [ip, #-4]

References Programming Techniques: Section 7.2.1 Interfacing C and Assembly Language, pp 7-4 and 7-5. Section 4.8 ARM Assembly Language Basics, pp 4-23, 4-24 and 4-25. Section 5.2.5 Exploring ARM Assembly Language, pp 5-6 and 5-7.

Page 4 of 4

Vous aimerez peut-être aussi