0% found this document useful (0 votes)
15 views61 pages

Chapter 08 ARM Subroutines 2 Stack Perserve Environment Edited

Chapter 8 of the document discusses the preservation of the environment via the stack in ARM Cortex-M microcontrollers. It covers how to call and return from subroutines, pass arguments, and manage the stack's growth direction and usage. The chapter emphasizes the importance of saving and restoring registers to maintain the runtime environment during subroutine calls.

Uploaded by

lynamyriam704
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views61 pages

Chapter 08 ARM Subroutines 2 Stack Perserve Environment Edited

Chapter 8 of the document discusses the preservation of the environment via the stack in ARM Cortex-M microcontrollers. It covers how to call and return from subroutines, pass arguments, and manage the stack's growth direction and usage. The chapter emphasizes the importance of saving and restoring registers to maintain the runtime environment during subroutine calls.

Uploaded by

lynamyriam704
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

Embedded Systems with ARM Cortex-M Microcontrollers in

Assembly Language and C

Chapter 8
Preserve Environment via Stack

Dr. Yifeng Zhu


Electrical and Computer Engineering
University of Maine

Spring 2020

Sommairement édité par JP David, Polytechnique Montréal


Merci au Dr. Yifeng Zhu pour l’autorisation d’utilisation
1
Overview
 How to call a subroutine?
 How to return the control back to the caller?
 How to pass arguments into a subroutine?
 How to return a value in a subroutine?
 How to preserve the running environment for the caller?

2
Stack
 A Last-In-First-Out memory model
 Only allow to access the most recently added item
 Also called the top of the stack
 Key operations:
 push (add item to stack)
 pop (remove top item from stack)
Tower of Hanoi

 Only one disk may be moved at a time.


 Each move consists of taking the upper disk from one of the rods and
sliding it onto another rod, on top of the other disks that may already be
present on that rod.
 No disk may be placed on top of a smaller disk.

4
Tower of Hanoi
STACK: Last In First Out

Stack 1 Stack 2 Stack 3

http://en.wikipedia.org/wiki/File:Tower_of_Hanoi_4.gif

5
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
6
Stack Growth Convention:
Full vs Empty

Stack base Stack base

Stack
Pointer Stack top Stack top
Stack
(SP) Pointer
(SP)

Full stack: SP points to the last item Empty stack: SP points to the
pushed onto the stack next free space on the stack
7
Cortex-M Stack
Memory
 Cortex-M uses full descending stack Address
0xFFFFFFFF

 Example:
PUSH/POP {r0,r6,r3}
 Stack pointer (SP, aka R13) Stack base
 decremented on PUSH
 SP = SP – 4 * # of registers
Stack
 incremented on POP Pointer
(SP)
Stack top

 SP = SP + 4 * # of registers
PUSH POP
stack grow
 SP starts at 0x20000200 for STM32- downwards

Discovery by default (can be changed in


startup.s)
0x00000000

8
Full Descending Stack
High Memory Addresses

PUSH {register_list}
equivalent to:
Stack base STMDB SP!, {register_list}
DB: Decrement Before

Stack POP {register_list}


Pointer Top of Stack equivalent to:
(SP)
LDMIA SP!, {register_list}
Stack grows toward
low memory IA: Increment After
addresses.

Low Memory Addresses

9
Stack Implementation
Push Pop
Stock Name
Equivalent Alternative Equivalent Alternative

Full
STMFD SP!,list STMDB SP!,list LDMFD SP!,list LDMIA SP!,list
Descending(FD)

Empty
STMED SP!,list STMDA SP!,list LDMED SP!,list LDMIB SP!,list
Descending(ED)

Full
STMFA SP!,list STMIB SP!,list LDMFA SP!,list LDMDA SP!,list
Ascending(FA)

Empty
STMEA SP!,list STMIA SP!,list LDMEA SP!,list LDMDB SP!,list
Ascending(EA)

10
Typical Usage of Stack
 Why need stack?
 Saving the original contents of processor’s registers at the
beginning a subroutine (Contents are restored at the end of a
subroutine)
 Storing local variables in a subroutine
 Passing extra arguments to a subroutine
 Saving processor’s registers upon an interrupt

Sound complex? No worry! We will learn them.

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

Push multiple registers


They are equivalent. PUSH {r8}
PUSH {r6, r7, r8} PUSH {r8, r7, r6} PUSH {r7}
PUSH {r6}

• 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
Stack
POP {Rd}
 Rd = (*SP) ⟶ full stack
 SP = SP + 4 ⟶ Stack shrinks

Pop multiple registers


They are equivalent.
POP {r6}
POP {r6, r7, r8} POP {r8, r7, r6} POP {r7}
POP {r8}

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

13
Full Descending Stack
PUSH {r3, r1, r7, r2}

14
Full Descending Stack
PUSH {r3, r1, r7, r2}

Largest-numbered
register is pushed first.

15
Full Descending Stack
PUSH {r3, r1, r7, r2} POP {r3, r1, r7, r2}

16
Full Descending Stack
PUSH {r3, r1, r7, r2} POP {r3, r1, r7, r2}

Smallest-numbered
register is popped first.

17
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

18
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

19
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

20
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

21
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

22
Quiz
Are the values of R1 and R2 swapped?

PUSH {R1, R2}


POP {R2, R1}

Answer: No.

But you can:


PUSH {R1, R2}
POP {R2}
POP {R1}
or
PUSH {R1}
PUSH {R2}
POP {R1, R2}

23
Subroutine
 A subroutines, also called a function or a procedure,
 single-entry, single-exit
 Return to caller after it exits
 When a subroutine is called, the Link Register (LR) holds the
memory address of the next instruction to be executed after
the subroutine exits.

24
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

25
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

26
Calling a Subroutine
BL label Caller Program

 Step 1: LR = PC + 4 MOV r4, #100


...
 Step 2: PC = label BL foo
...

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

27
Exiting a Subroutine
Caller Program

MOV r4, #100


...
BL foo
...

Subroutine/Callee
foo PROC
Branch and Exchange ...
BX LR MOV
...
r4, #10

BX LR
 PC = LR ENDP

28
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 Yes/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 the
r12 (IP) Intra-procedure-call register No
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

29
Caller-saved Registers vs
Callee-saved Registers
32 bits

Caller-saved
R0 • Not saved by subroutine
registers
R1
• Hold arguments/result
R2
Low R3
Registers
R4
• Caller expects their values are
R5
Callee-saved General retained
R6
registers
Purpose
Register • Callee must save and store it if
R7
callee modifies it
R8
R9
High
32 bits
Registers R10
R11 xPSR
R12 BASEPRI
Special
R13 (SP) R13 (MSP) R13 (PSP) PRIMASK Purpose
Register
Callee-saved registers R14 (LR) FAULTMASK
R15 (PC) CONTROL

30 Register Bank Special Registers


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

Caller expects callee does not modify r4! Callee should preserve r4!

31
Preserve Runtime Environment via Stack

Caller Program Subroutine/Callee

Caller should save these registers if Callee should Preserve


callers needs to re-use their original • R4 – R11
values: • R14 (LR)
• R0 – R3 • R13 (SP)
• R12
• CPSR

32
Preserve Runtime Environment via Stack
What is wrong in foo()?
Caller Program Subroutine foo Subroutine bar
foo PROC bar PROC
MOV r4, #100 PUSH {r4} ...
... ... BX LR
BL foo MOV r4, #10 ENDP
... ...
ADD r4, r4, #1 BL bar
...
POP {r4}
BX LR
ENDP

33
Preserve Runtime Environment via Stack
What is wrong in foo()?
Caller Program Subroutine foo Subroutine bar
foo PROC bar PROC
MOV r4, #100 PUSH {r4} ...
... ... BX LR
BL foo MOV r4, #10 ENDP
... ...
ADD r4, r4, #1 BL bar
...
POP {r4}
BX LR
ENDP

34
Preserve Runtime Environment via Stack
What is wrong in foo()? Solution #1
Caller Program Subroutine foo Subroutine bar
foo PROC bar PROC
MOV r4, #100 PUSH {r4, LR} ...
... ... BX LR
BL foo MOV r4, #10 ENDP
... ...
ADD r4, r4, #1 BL bar
...
POP {r4, LR}
BX LR
ENDP

35
Stacks and Subroutines
Preserve Runtime Environment via Stack
What is wrong in foo()? Solution #2
Caller Program Subroutine foo Subroutine bar
foo PROC bar PROC
MOV r4, #100 PUSH {r4, LR} ...
... ... BX LR
BL foo MOV r4, #10 ENDP
... ...
ADD r4, r4, #1 BL bar
...
POP {r4, PC}
BX LR
ENDP

37
Subroutine Calling Another Subroutine

MAIN QUAD PUSH {LR}


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

Function SQ
Function MAIN Function QUAD

38
Subroutine Calling Another Subroutine

MAIN PROC QUAD PROC


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

Function QUAD

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

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

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

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

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

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... Preserve POP {LR} 0x08000158


Link Register (LR) BX LR 0x0800015C

42
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000140
BL SQ BX LR 0x08000148
PC 0x08000150
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

43
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000154
BL SQ BX LR 0x08000148
PC 0x08000144
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

44
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000154
BL SQ BX LR 0x08000148
PC 0x08000148
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

45
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000154
BL SQ BX LR 0x08000148
PC 0x08000154
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

46
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000158
BL SQ BX LR 0x08000148
PC 0x08000144
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

47
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000158
BL SQ BX LR 0x08000148
PC 0x08000148
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

48
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x200001FC
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000158
BL SQ BX LR 0x08000148
PC 0x08000158
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

49
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x20000200
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000140
BL SQ BX LR 0x08000148
PC 0x0800015C
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... Restore POP {LR} 0x08000158


Link Register (LR) BX LR 0x0800015C

50
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
BX LR BL QUAD 0x0800013C
B ENDL 0x08000140
SP 0x20000200
QUAD PUSH {LR} SQ MUL R0,R0 0x08000144
LR 0x08000140
BL SQ BX LR 0x08000148
PC 0x08000140
BL SQ QUAD PUSH {LR} 0x0800014C

POP {LR} BL SQ 0x08000150

BX LR BL SQ 0x08000154

ENDL ... POP {LR} 0x08000158


BX LR 0x0800015C

51
Stack Pointer (SP)
32 bits • SP is the shadow of MSP (Main SP) or PSP (Process SP)
• If there is no embedded OS, PSP is not used
R0 • Determined by the ASP (Active SP) bit in the CONTROL
R1 register (ASP is always 0 in handler mode).
R2 • 0 = MSP (default)
Low R3 • 1 = PSP
Registers
R4 Bit 31 - 3 2 1 0
R5
R6
General
Purpose
Reserved ASP
Register
R7 CONTROL Register
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

52 Register Bank Special Registers


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.

53
Passing Arguments into a Subroutine
R0 R1 R2 R3
32-bit 32-bit 32-bit 32-bit
Argument 1 Argument 2 Argument 3 Argument 4 Extra arguments are
pushed to the stack by
R1(MSB32) R0(LSB32) R3(MSB32) R2(LSB32) the caller. The caller is
64-bit Argument 1 64-bit Argument 2 responsible to pop them
out of the stack after the
subroutine returns.
R3(MSB32) R2 R1 R0(LSB32)
128-bit Argument

Subroutine

R0 R1(MSB32) R0(LSB32) R3(MSB32) R2 R1 R0(LSB32)


32-bit Return Value 64-bit Return Value 128-bit Return Value

54
Passing Arguments into a Subroutine

int32_t sum(int16_t a16, int16_t b16, int8_t c8, int32_t d32);

a16 b16 c8 d32


Register R0 Register R1 Register R2 Register R3

Subroutine

Return Value
Register R0

55
Passing 4 Arguments

int32_t sum(int16_t a16, int16_t b16, int8_t c8, int32_t d32);

s = sum(1, 2, 3, 4);

Caller Callee

MOVS r0, #1 ; a16 sum PROC


MOVS r1, #2 ; b16 ADD r0, r0, r1 ; a16 + b16
MOVS r2, #3 ; c8 ADD r0, r0, r2 ; add c8
MOVS r3, #4 ; d32 ADD r0, r0, r3 ; add d32
BL sum BX LR ; return
ENDP

56
Passing Extra Arguments via Stack
int32_t sum(int32_t a, int32_t b, int32_t c, int32_t d,
int32_t h, int32_t i, int32_t j, int32_t k);
s = sum(1, 2, 3, 4, 5, 6, 7, 8);

Caller Callee
MOVS r0, #5 sum PROC
MOVS r1, #6 EXPORT sum
MOVS r2, #7 ADD r0, r0, r1 ; add a + b
MOVS r3, #8 ADD r0, r0, r2 ; add c
PUSH {r0, r1, r2, r3} ADD r0, r0, r3 ; add d
MOVS r0, #1 LDRD r1,r2, [sp] ; r1=mem[sp],r2=mem[sp+4]
MOVS r1, #2 ADD r0, r0, r1 ; add h
MOVS r2, #3 ADD r0, r0, r2 ; add i
MOVS r3, #4 LDRD r1,r2, [sp, #8] ; r1=mem[sp+8],r2=mem[sp+12]
BL sum ADD r0, r0, r1 ; add j
... ADD r0, r0, r2 ; add k
POP {r0, r1, r2, r3} BX LR
ENDP

LDRD: Load Register Doubleword


57
Passing Extra Arguments via Stack
int32_t sum(int32_t a, int32_t b, int32_t c, int32_t d,
int32_t h, int32_t i, int32_t j, int32_t k);
s = sum(1, 2, 3, 4, 5, 6, 7, 8);

Caller Callee
MOVS r0, #5 sum PROC
MOVS r1, #6 EXPORT sum
MOVS r2, #7 PUSH {r5, r6, lr}
MOVS r3, #8 ADD r0, r0, r1 ; add a + b
PUSH {r0, r1, r2, r3} ADD r0, r0, r2 ; add c
MOVS r0, #1 ADD r0, r0, r3 ; add d
MOVS r1, #2 LDRD r5,r6, [sp, #12] ;r5=mem[sp+12],r6=mem[sp+16]
MOVS r2, #3 ADD r0, r0, r5 ; add h
MOVS r3, #4 ADD r0, r0, r6 ; add i
BL sum LDRD r5,r6, [sp, #20] ;r5=mem[sp+20],r6=mem[sp+24]
... ADD r0, r0, r5 ; add j
POP {r0, r1, r2, r3} ADD r0, r0, r6 ; add k
POP {r5, r6, pc}
ENDP
58
Passing Extra Arguments via Stack
int32_t sum(int32_t a, int32_t b, int32_t c, int32_t d,
int32_t h, int32_t i, int32_t j, int32_t k);
s = sum(1, 2, 3, 4, 5, 6, 7, 8);

Caller Stack
MOVS r0, #5 Old SP <xxxxxxxx>
MOVS r1, #6
MOVS r2, #7
SP+12 0x00000008
MOVS r3, #8 SP+8 0x00000007
PUSH {r0, r1, r2, r3}
MOVS r0, #1 SP+4 0x00000006
MOVS r1, #2 SP 0x00000005
MOVS r2, #3
MOVS r3, #4
BL sum
...
POP {r0, r1, r2, r3}

59
Passing Extra Arguments via Stack
int32_t sum(int32_t a, int32_t b, int32_t c, int32_t d,
int32_t h, int32_t i, int32_t j, int32_t k);
s = sum(1, 2, 3, 4, 5, 6, 7, 8);
Callee
Stack
Old SP <xxxxxxxx> sum PROC
EXPORT sum
SP+24 0x00000008 PUSH {r5, r6, lr}
SP+20 0x00000007 ADD r0, r0, r1 ; add a + b
ADD r0, r0, r2 ; add c
SP+16 0x00000006 ADD r0, r0, r3 ; add d
SP+12 0x00000005 LDRD r5,r6, [sp, #12] ; r5=mem[sp+12],r6=mem[sp+16]
ADD r0, r0, r5 ; add h
SP+8 lr ADD r0, r0, r6 ; add i
SP+4 r6 LDRD r5,r6, [sp, #20] ; r5=mem[sp+20],r6=mem[sp+24]
ADD r0, r0, r5 ; add j
SP r5 ADD r0, r0, r6 ; add k
POP {r5, r6, pc}
ENDP
60
Summary
 ARM Cortex-M uses full descending stack
 How to pass arguments into a subroutine?
 Each 8-, 16- or 32-bit variables is passed via r0, r1, r2, r3
 Extra parameters are passed via stack
 What registers should be preserved?
 Caller-saved registers vs callee-saved registers
 How to preserve the running environment for the caller?
 Via stack

61

You might also like