Download as pdf or txt
Download as pdf or txt
You are on page 1of 51

Chapters 8

Stacks and Subroutines


Embedded Systems with ARM Cortext-M
Updated: Tuesday, March 6, 2018
Basic Idea
lLarge programs are hard to handle
lWe can break them to smaller programs
lThey are called subroutines
lSubroutines are called from the main program
lWriting subroutines
lWhen should we jump? (use CALL)
lWhere do we return to? (use RETURN)
Subroutine

l A subroutine is a block of code that is called from different places from within a main program or
other subroutines.
l Saves code space in that the subroutine code does not have to be repeated in the program areas
that need it;
l Only the code for the subroutine call is repeated.
l A subroutine can have
l parameters that control its operation
l local variables for computation.
l A subroutine may pass a return value back to the caller.
l Space in data memory must be reserved for parameters, local variables, and the return value.
Subroutine
Using Subroutines
• When using subroutines we need to know the following:
• Where is the NEXT instruction s address
• How to remember the RETURN address
• Subroutines are based on MPU instructions and use STACK

Let’s Review Stacks and then we come back to subroutines!


Stack Memory
Address
0xFFFFFFFF

lTemporary memory storage


space used during the
execution of a program Stack base

lUsed by MPU STKPTR


lStack Pointer (SP) Stack top

lThe MPU uses a register called PUSH POP


the stack pointer, similar to the Stack grows
downwards

program counter (PC), to keep


track of available stack locations.
0x00000000
Data Storage via the Stack
• The word stack is used because storage/retrieval of words
in the stack memory area is the same as accessing items
from a stack of items.
• Visualize a stack of boxes. To build a stack, you place box A,
then box B, then box C
• Notice that you only have access to the last item placed on the stack (the Top of Stack –
TOS). You retrieve the boxes from the stack in reverse order (C then B then A). A stack is
also called a LIFO (last-in-first-out) buffer (similar to a Queue)

GENERALLY set in SRAM 0x20000600 Area


Instructions to Store and Retrieve Information from the
Stack
lPUSH
lIncrement the memory address in the stack pointer (by one) and
stores the contents of the counter (PC+2) on the top of the stack
lPOP
lDiscards the address of the top of the stack and decrement the
stack pointer by one
Example
lWhat is the value of PC (PC=PC+2), and STKPTR as you execute each
line?

nPC TOS STKPTR REG


W MOV R0, #2
22 0 0 00 MOV R0, #2
24 0 0 20 MOV R0, #2
26 26 1 20
28 28 2 20
2A 26 1 20
2C 0 0 20
Stack Growth Convention:
Ascending vs Descending Memory Memory
Address Address
0xFFFFFFFF 0xFFFFFFFF

Stack grows
upwards
Stack base PUSH POP

Stack top

Stack top

PUSH POP Stack base


Stack grows
downwards

0x00000000 0x00000000

Descending stack: Stack grows Ascending stack: Stack grows


towards low memory address towards high memory address
10
Cortex-M Stack Memory
• stack pointer (SP) = R13 Address
0xFFFFFFFF

• Cortex-M uses full descending


stack
• stack pointer Stack base

• decremented on PUSH
• incremented on POP
Stack
• SP starts at 0x20000600 for Pointer Stack top

STM32F401xe devices (SP)

PUSH POP
stack grow
downwards

0x00000000

11
Stack
PUSH {Rd}
• SP = SP-4 ⟶ descending stack
• (*SP) = Rd ⟶ full stack

Push multiple registers


Highest Memory
LM HM They are equivalent. PUSH {r8}
PUSH {r6, r7, r8} PUSH {r8, r7, r6} PUSH {r7}
PUSH {r6}
Lowest Memory

• The order in which registers listed in the register list does not matter.
• When pushing multiple registers, these registers are automatically
sorted by name and the lowest-numbered register is stored to the
lowest memory address, i.e. is stored last.

12
Example: swap R1 & R2
R1 0x11111111
R2 0x22222222

R13 (SP) 0x20000200 Address


PUSH {R1}
PUSH {R2} xxxxxxxx 0x20000200
POP {R1} xxxxxxxx 0x200001FC
POP {R2} xxxxxxxx 0x200001F8

memory

13
Example: swap R1 & R2
R1 0x11111111
R2 0x22222222

R13 (SP) 0x200001FC Address


PC PUSH {R1}
PUSH {R2} xxxxxxxx 0x20000200
POP {R1} 0x11111111 0x200001FC
POP {R2} xxxxxxxx 0x200001F8

memory

14
Example: swap R1 & R2
R1 0x11111111
R2 0x22222222

R13 (SP) 0x200001F8 Address


PUSH {R1}
PC PUSH {R2} xxxxxxxx 0x20000200
POP {R1} 0x11111111 0x200001FC
POP {R2} 0x22222222 0x200001F8

memory

15
Example: swap R1 & R2
R1 0x22222222
R2 0x22222222

R13 (SP) 0x200001FC Address


PUSH {R1}
PUSH {R2} xxxxxxxx 0x20000200
PC POP {R1} 0x11111111 0x200001FC
POP {R2} 0x22222222 0x200001F8

memory

16
Example: swap R1 & R2
R1 0x22222222
R2 0x11111111

R13 (SP) 0x20000200 Address


PUSH {R1}
PUSH {R2} xxxxxxxx 0x20000200
POP {R1} 0x11111111 0x200001FC
PC POP {R2} 0x22222222 0x200001F8

memory

17
Quiz Descending SP
Are the values of R1 and R2 swapped?
Highest Memory
PUSH {R1, R2}
PUSH {r2}
POP {R2, R1} PUSH {r1}
Lowest Memory

18
Quiz Descending SP
Are the values of R1 and R2 swapped?
Highest Memory
PUSH {R1, R2} ; Push R2 then R1 PUSH {r2}
POP {R2, R1} ; POP R1 then R2 PUSH {r1}
Lowest Memory

Answer: No.

But you can:


PUSH {R1, R2}
POP {R2}
POP {R1} POPing out of order!
or
PUSH {R1}
PUSH {R2}
POP {R1, R2}

19
Back to Subroutine
• In general, a subroutines, also called a function or a procedure,
• single-entry, single-exit
• Return to caller after it exits
• In ARM:
• When a subroutine is called, the Link Register (LR) holds the memory address
of the next instruction to be executed after the subroutine exits.

20
Link Register
32 bits

R0 Link Register (LR) holds the return address


R1 of the current subroutine call.
R2
Low R3
Registers
R4
R5
General
R6 Purpose
Register
R7
R8
R9
High
32 bits
Registers R10
R11 xPSR
R12 BASEPRI
Special
R13 (SP) R13 (MSP) R13 (PSP) PRIMASK Purpose
Register
R14 (LR) FAULTMASK
R15 (PC) CONTROL

21
Call a Subroutine

Caller Program Subroutine/Callee


foo PROC
MOV r4, #100 ...
... MOV r4, #10 ; foo changes r4
BL foo ...
... BX LR
ADD r4, r4, #1 ; r4 = 101, not 11 ENDP
Calling a Subroutine
BL label Caller Program

• Step 1: LR = PC + 4 (Return address) MOV r4, #100

• Step 2: PC = label (Next instruction) ...


BL foo
MOV. R5,#2
...

• Notes: Subroutine/Callee
• label is name of subroutine foo PROC
...
• Compiler translates label to memory address MOV r4, #10
• After call, LR holds return address (the ...
instruction following the call) BX LR
ENDP

Subroutine: A New Process


23
Exiting a Subroutine
BX LR Caller Program

• PC = LR MOV r4, #100


...
BL foo
...

Subroutine/Callee
foo PROC
...
MOV r4, #10
...
BX LR
ENDP

24
ARM Procedure Call Standard Subroutine
Register Usage Notes
Preserved
If return has 64 bits, then r0:r1 hold it. If argument 1 has
r0 Argument 1 and return value No
64 bits, r0:r1 hold it.
r1 Argument 2 No
r2 Argument 3 No If the return has 128 bits, r0-r3 hold it.
r3 Argument 4 No If more than 4 arguments, use the stack
r4 General-purpose V1 Yes Variable register 1 holds a local variable.
r5 General-purpose V2 Yes Variable register 2 holds a local variable.
r6 General-purpose V3 Yes Variable register 3 holds a local variable.
r7 General-purpose V4 Yes Variable register 4 holds a local variable.
r8 General-purpose V5 YES Variable register 5 holds a local variable.
r9 Platform specific/V6 No Usage is platform-dependent.
r10 General-purpose V7 Yes Variable register 7 holds a local variable.
r11 General-purpose V8 Yes Variable register 8 holds a local variable.
It holds intermediate values between a procedure and
r12 (IP) Intra-procedure-call register No
the sub-procedure it calls.
r13 (SP) Stack pointer Yes SP has to be the same after a subroutine has completed.
LR does not have to contain the same value after a
r14 (LR) Link register No
subroutine has completed.
r15 (PC) Program counter N/A Do not directly change PC

25
Link Register
32 bits

R0
Scratch registers, not saved by
R1 subroutine. Hold
R2 arguments/result
Low R3
Registers
R4
R5
R6
General
Purpose
Callee must save them.
R7
Register
Caller expects these values
R8 are retained .
R9
High
32 bits
Registers R10
R11 xPSR
Link Register R12 BASEPRI
Special
R13 (SP) R13 (MSP) R13 (PSP) PRIMASK Purpose
Register
R14 (LR) FAULTMASK
R15 (PC) CONTROL

26
Preserve Runtime Environment via Stack
Caller Program Subroutine/Callee
foo PROC
MOV r4, #100 PUSH {r4} ; preserve r4
... ...
BL foo MOV r4, #10 ; foo changes r4
... ...
ADD r4, r4, #1 ; r4 = 101, not 11 POP {r4} ; Recover r4
BX LR
ENDP

Callee must save R4 and beyond.


Caller expects these values to be retained

27
Stacks and Subroutines
Where is the ADD INSTRUCTION
Return Address saved?

ADD INSTRUCTION
Stacks and Subroutines Saving PC1+4: ADD INSTRUCTION

ADD INSTRUCTION
Subroutine Calling Another Subroutine

MAIN QUAD PUSH {LR}


MOV R0,#2 BL SQ SQ MUL R0,R0
BL QUAD BL SQ BX LR
POP {LR}
ENDL ...
BX LR

Function SQ
Function MAIN Function QUAD

30
Subroutine Calling Another Subroutine

MAIN PROC QUAD PROC


MOV R0,#2 PUSH {LR} SQ PROC
BL QUAD BL SQ MUL R0,R0
BL SQ BX LR
ENDL ...
POP {LR} ENDP
ENDP
BX LR
Function MAIN ENDP Function SQ

Function QUAD

31
Example: R0 = R04 Descending Stack

MOV R0,#2 xxxxxxxx 0x20000200


BL QUAD 0x200001FC
B ENDL 0x200001F8
R0
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x20000200
SQ MUL R0,R0 0x08000144
LR
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000138
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
32
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x200001FC
B ENDL 0x200001F8
R0 0x02
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x20000200
SQ MUL R0,R0 0x08000144
LR
BX LR 0x08000148
QUAD PUSH {LR} PC 0x0800013C
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
33
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x200001FC
B ENDL 0x200001F8
R0 0x02
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x20000200
SQ MUL R0,R0 0x08000144
LR 0x08000140
BX LR 0x08000148
QUAD PUSH {LR} PC 0x0800014C
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
Preserve POP {LR} 0x08000158
BX LR Link Register (LR) BX LR 0x0800015C
ENDL ...
34
Example: R0 = R04
MOV R0,#2 Note: xxxxxxxx 0x20000200
BL QUAD The address is saved 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x02
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000140
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000150
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
35
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x02
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000154
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000144
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
36
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x04
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000154
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000148
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
37
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x04
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000154
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000154
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
38
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x04
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000158
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000144
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
39
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x10
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000158
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000148
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
40
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x10
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x200001FC
SQ MUL R0,R0 0x08000144
LR 0x08000158
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000158
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
41
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x10
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x20000200
SQ MUL R0,R0 0x08000144
LR 0x08000140
BX LR 0x08000148
QUAD PUSH {LR} PC 0x0800015C
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
Recover POP {LR} 0x08000158
BX LR Link Register (LR) BX LR 0x0800015C
ENDL ...
42
Example: R0 = R04
MOV R0,#2 xxxxxxxx 0x20000200
BL QUAD 0x08000140 0x200001FC
B ENDL 0x200001F8
R0 0x10
MOV R0,#2 0x08000138
SQ
MUL R0,R0 BL QUAD 0x0800013C

BX LR B ENDL 0x08000140
SP 0x20000200
SQ MUL R0,R0 0x08000144
LR 0x08000140
BX LR 0x08000148
QUAD PUSH {LR} PC 0x08000140
QUAD PUSH {LR} 0x0800014C
BL SQ
BL SQ 0x08000150
BL SQ
BL SQ 0x08000154
POP {LR}
POP {LR} 0x08000158
BX LR
BX LR 0x0800015C
ENDL ...
43
Initializing the stack pointer (SP)
• Before using the stack, software has
to define stack space and initialize
the stack pointer (SP).
• The assembly file startup.s defines
stack space and initialize SP.

44
STACK

Example: R0 = R04 R0 0x20000200


0x200001FC
0x200001F8

Top of the Stack SP MOV R0,#2 0x08000138


RETURN ADDRESS LR BL QUAD 0x0800013C
Next Instruction PC ENDL B ENDL 0x08000140
SQ MUL R0,R0 0x08000144
BX LR 0x08000148
QUAD PUSH {LR} 0x0800014C
BL SQ 0x08000150
BL SQ 0x08000154
POP {LR} 0x08000158

Find PC, LR, and SP values as you execute BX LR 0x0800015C

each line of code. What is happening?


45
STACK

Example: R0 = R04 R0
8000140
0x20000200
0x200001FC
0x200001F8

Top of the Stack SP 200001F8 MOV R0,#2 0x08000138


RETURN ADDRESS LR BL QUAD 0x0800013C
Next Instruction PC ENDL B ENDL 0x08000140
SQ MUL R0,R0 0x08000144
BX LR 0x08000148
QUAD PUSH {LR} 0x0800014C
BL SQ 0x08000150
BL SQ 0x08000154
POP {LR} 0x08000158

Find PC, LR, and SP values as you execute BX LR 0x0800015C

each line of code. What is happening?


46
Let’s practice a little more….
Using Push & Pop
Calling a Subroutine
• Note that R0 and R1 can be
used as the arguments
• PUSH and POP can be used
to store the values
Calling a Subroutine from a different source
file (sum3.s) from the __main
Practice
• Find PC, LR, and SP
values as you execute
each line of code. What
is happening?
Instruction Location PC LR SP

You might also like