Professional Documents
Culture Documents
Assembly Language
1
Embedded Programming
In an embedded system the programmer must pay closer attention to:
➢ The memory architecture
➢ The I/O capabilities
➢ Interrupt handling
➢ The memory map: The sizes and addresses of the RAM and ROM in the MCU in hand.
➢ What data types the compiler supports and how they are stored in memory
➢ The MCU I/O capabilities and the addresses to access I/O registers (Control/Status/Data)
Easier to read, understand & change code Difficult to maintain assembly code
You have to master only one language Each target m/c has its own assembly
Minimum m/c code size not guaranteed Optimized m/c code size
void main(void) {
..
➢ A function may take arguments (parameters) and may .
return a result value. J();
..
.
K();
..
➢ A function may call other functions .
}
5
C Run-Time Start-Up Module
▪ After power-up or reset, CPU executes the reset RAM Flash ROM
exception handler (Reset_Handler), which is
Fill with
located in startup_MKL25Z4.s, to do the Zero-Initialized Data Initialization Data
a, b zeros 31
following before main function can execute:
1. Initialize hardware Initialized Data Constant Data
d c: 123
▪ Clock configuration
Hello!
▪ Peripherals’ setup
Stack Startup and Runtime
2. Initialize C or C++ run-time environment e, f Library Code
▪ Initialize stack pointer
▪ Initialize variables Heap Data Code
▪ Set up heap memory
6
MEMORY REQUIREMENTS
7
Types of Memory
ROM RAM
ROM: Static RAM (SRAM):
Contains data that is specified when the IC is fabricated. Retains data as long as the power is on.
Flash EEPROM:
Erased and reprogrammed electrically entire page at a
time. (Used for code and constant data)
Typically, MCUs have integrated: Some MCUs have address and data busses available
1. flash on their pins to allow external memory expansion.
2. SRAM (DRAM/SRAM/Flash)
Some MCUs have EEPROM.
8
What Memory Does a Program Need?
➢ Should information (code or data) persist even with no power?
This information need to be placed in ROM, EEPROM, or Flash.
➢ How long does the data need to exist? (what is its lifetime)
▪ Data that must exist for the entire duration of the program execution must be given a permanent location in
memory. This is called static data.
▪ Temporary data is stored in RAM that is reused by different parts of the program. The program can use two
reusable memory sections:
1. The call stack space which is automatically allocated on function entry and deallocated on function exit.
2. The heap which is explicitly allocated and deallocated by the programmer.
9
What Memory Does a Program Need?
Five possible types
▪ Code
▪ Read-only static data
▪ Writable static data
◦ Initialized by start-up code
◦ Zero-initialized by compiler
◦ Uninitialized
▪ Stack
▪ Heap
10
Program Memory Use
Some data variables needs initialization, and some do not: Can the information change?
▪ No? Put it in read-only, nonvolatile memory
▪ Initialized variables:
▪ Instructions
1. Static data has a fixed memory address, so it is ▪ Constant strings
initialized at program start-up by copying the initial
▪ Constant operands
values from the read only memory.
▪ Initialization values
2. Automatically allocated data is initialized by the
program upon allocation. ▪ Yes? Put it in read/write memory
▪ Variables
▪ Uninitialized variables: ▪ Intermediate computations
1. Static variables are initialized to zero. ▪ Return address
▪ Other housekeeping data
2. Automatically or dynamically allocated variables have
undefined values.
11
C Data Types for Cortex-M 32-bit Core
C type stdint.h type Bits Sign Range
char uint8_t 8 Unsigned 0 .. 255
Integer Data Types
Qualifiers signed and unsigned may be applied to data types char and integer.
• signed Ex: signed int i (default for CW C compiler)
• unsigned Ex: unsigned int i (i holds positive values only)
13
Constant Declaration
Types of constants in C:
▪ Dynamically allocated
◦ Exists from explicit allocation to explicit
de-allocation
◦ Space can be reused
15
Program Memory Use
RAM Flash ROM
Zero-Initialized int a, b;
Constant Data
Data const char c=123;
int d=31;
Initialized Data void main(void) { Initialization
int e; Data
char f[32]; Startup and
Stack e = d + 7; Runtime Library
a = e + 29999; Code
strcpy(f,“Hello!”);
Heap Data } Program .text
16
CALLING FUNCTIONS
17
Function Declaration
It is important for the C programmer to distinguish the two terms declaration and definition.
➢ A function declaration specifies its name, its input parameters and its output parameter.
➢ A function definition specifies the exact sequence of operations to execute when it is called.
A function definition will generate object code.
For example, the declaration for the function UART_OutChar could be written as
void UART_OutChar(char);
We can see that the declaration shows how to use the function, not how the function works.
Because the C compilation is a one-pass process, an object must be declared (or defined) before it can be used.
18
Function Arguments and Return Values
• A program is made of one or more functions, with each made of a series of statements.
• A function may take arguments (parameters) and may return a result value.
➢ To execute a function:
19
Passing Arguments
▪ How to pass them?
Much faster to use registers than stack
Not always feasible because quantity of registers is
limited.
20
Return Values
▪ Called function passes Return Value in register(s) or stack.
1. Registers
Faster but limited number (only four registers)
2. Stack
• Calling function allocates space for return value, then passes
pointer to space as an argument to called function.
• Called function stores result at location indicated by pointer.
• Result was returned in r0, so add to r4 (a2 += result) 0000ec 1904 ADDS r4,r0,r4
22
Call and Return Example
int fun3(int b1,int b2,int b3, int b4)
{
return b1*b2*b3*b4;
}
fun3 PROC
;;;81 int fun3(int b1, int b2, int b3, int b4)
{
• Save r4 and Link Register on stack 0000ba b510 PUSH {r4,lr}
• r0 = b1*b2 0000c0 4348 MULS r0,r1,r0
• r0 *= b3 0000c2 4350 MULS r0,r2,r0
• r0 *= b4 0000c4 4358 MULS r0,r3,r0
Return value is in r0
• Restore r4 and return from subroutine 0000c6 bd10 POP {r4,pc}
23
FUNCTION PROLOG AND EPILOG
24
Prolog and Epilog
Function object code contains three sections:
1. Prolog: Initial code in function which:
‒ Saves registers on the call stack by a push instruction.
‒ Initializes automatic variables if needed.
‒ Prepares activation record.
25
Return Address
▪ Return address stored in LR by bl, blx instructions
▪ After c() returns, b() will have lost its return address
26
Function Prolog and Epilog Example
fun4 PROC
;;;102 int fun4(char a, int b, char c)
{
▪ Save r4 (preserved register) and link ;;;103 volatile int x[8];
register (return address) 00010a b510 PUSH {r4,lr}
▪ Allocate 32 (0x20) bytes on stack for 00010c b088 SUB sp,sp,#0x20
array x by subtracting from SP ...
27
Activation Record Creation by Prolog
Smaller address space for x[0] ← 3. SP after sub sp,sp,#0x20
space for x[1]
space for x[2]
space for x[3]
Array x
space for x[4]
space for x[5]
space for x[6]
space for x[7]
lr Return address ← 2. SP after push {r4,lr}
r4 Preserved register
Larger address Caller’s stack frame ← 1. SP on entry to function,
before push {r4,lr}
28
Activation Record Destruction by Epilog
Smaller address space for x[0] ← 1. SP before add sp,sp,#0x20
space for x[1]
space for x[2]
space for x[3]
Array x
space for x[4]
space for x[5]
space for x[6]
space for x[7]
lr Return address ← 2. SP after add sp,sp,#20
r4 Preserved register
Larger address Caller’s stack frame ← 3. SP after pop {r4,pc}
29
USING REGISTERS
30
AAPCS Register Use Conventions
The AAPCS specification defines a set of conventions that must be followed by compilers.
▪ When calling a subroutine, the calling subroutine permits some registers to be overwritten by the subroutine
(scratch registers), whereas others are expected to retain their values upon return.
▪ Scratch registers: r0-r3 are not expected to be preserved upon returning from a called subroutine
▪ Preserved registers: r4-r8, r10-r11 (“variable”) registers are expected to have their original values upon
returning from a called subroutine
▪ If a subroutine needs to use a preserved register it needs to save its value before overwriting. Before
completion, the subroutine needs to restore the preserved register to its original value.
The ARM Architecture Procedure Call Standard (AAPCS):
▪ Use R0-R3 to pass input parameters into a C function
▪ Functions must preserve the values of registers R4-R11.
▪ Place the return parameter in register R0.
▪ Push and pop an even number of registers to maintain an 8-byte alignment on the stack.
31
AAPCS Core Register Use Conventions
Preserved registers:
Must be saved, restored by called
procedure if it will modify them.
Calling subroutine expects these to
retain their value.
Scratch registers:
Don’t need to be saved. May be
used for arguments, results, or
temporary values.
32
Activation Record (Stack Frame) and Call Stack
Activation record:
Temporary storage in memory for function’s preserved registers, arguments,
local variables, return address, etc. Exists only from function’s start to end.
Also called stack frame.
Lower
▪ Calling a function creates an activation address (Free stack space)
35
Accessing Data int siA;
void static_auto_local() {
Q) What does it take to get at a variable in memory? int aiB;
static int siC=3;
int * apD;
A) Depends on location, which depends on storage type: int aiE=4, aiF=5, aiG=6;
• Static
siA = 2;
Has a permanent location in memory. Mostly aiB = siC + siA;
accessed through an offset from the PC (PC relative) apD = & aiB;
(*apD)++;
• Automatic apD = &siC;
(*apD) += 9;
Stored on the stack. Accessed through an offset from
apD = &siA;
the SP. apD = &aiE;
apD = &aiF;
• Dynamic apD = &aiG;
Accessed through a pointer which is another data (*apD)++;
variable. aiE+=7;
*apD = aiE + aiF;
}
36
Static Variables
▪ Static variable can be located anywhere in 32-bit memory space, 1) Load r0 with pointer to variable
so need a 32-bit pointer 2) Load r1 from [r0]
3) Use value of variable
▪ Can’t fit a 32-bit pointer into a 16-bit instruction (or a 32-bit
instruction), so: Label:
save the pointer separate from instruction, but nearby 32-bit pointer to Variable
to access it with a short PC-relative offset
▪ Can now load variable’s value into a register (r1) from memory
using that pointer in r0
37
Static Variables
▪ Key AREA ||.text||, CODE, READONLY, ALIGN=2
▪ variable’s value ;;;20 siA = 2;
▪ variable’s address 00000e 2102 MOVS r1,#2
▪ address of copy of variable’s address 000010 4a37 LDR r2,|L1.312|
▪ Code 000012 6011 STR r1,[r2,#0] ; siA
▪ Loads r2 with address of siA (from ;;;21 aiB = siC + siA;
|L1.312|) 000014 4937 LDR r1,|L1.316|
▪ Loads r1 with contents of siA (via 000016 6809 LDR r1,[r1,#0] ; siC
pointer r2, with offset 0) 000018 6812 LDR r2,[r2,#0] ; siA
▪ Same for siC, with address at |L1.244| 00001a 1889 ADDS r1,r1,r2
00001c 9103 STR r1,[sp,#0xc]
|L1.312|
▪ Addresses of siA and siC are stored as DCD ||siA||
literals to be loaded into pointers |L1.316|
DCD ||siC||
AREA ||.data||, DATA, ALIGN=2
▪ Variables siC and siA are located in .data
||siC||
section with initial values
DCD 0x00000003
||siA||
38
DCD 0x00000000
Automatic Variables Stored on Stack
int main(void) {
▪ Automatic variables are stored in a function’s activation record. auto vars
(unless optimized and promoted to register) a();
}
▪ Activation records are located on the stack void a(void) {
auto vars
▪ Calling a function creates an activation record, allocating space on stack. b();
}
▪ Returning from a function deletes the activation record, freeing up space
on stack void b(void) {
auto vars
c();
}
void c(void) {
auto vars
…
}
39
Automatic Variables
int main(void) {
auto vars Lower
a(); (Free stack space)
address
} <- Stack pointer while
Local storage
Activation record for executing c
void a(void) { current function C Saved regs
auto vars Arguments (optional)
b(); Activation record for Local storage <- Stack pointer while
} caller Saved regs executing b
function B Arguments (optional)
void b(void) { Activation record for Local storage <- Stack pointer while
auto vars caller’s caller function Saved regs executing a
c(); A Arguments (optional)
} Higher Activation record for Local storage <- Stack pointer while
address caller’s caller’s caller Saved regs executing main
void c(void) { function main Arguments (optional)
auto vars
…
}
40
Addressing Automatic Variables
➢ Program must allocate space on stack for variables.
➢ An automatically allocated variable is stored at a specific offset from the Address Contents
stack pointer.
SP
SP+4
➢ Stack addressing uses an offset from the stack pointer: [sp, #offset]
SP+8
▪ One byte used for offset, is multiplied by four SP+0xC
SP+0x10
▪ Possible offsets: 0, 4, 8, …, 1020
SP+0x14
▪ Maximum range addressable this way is 1024 bytes SP+0x18
SP+0x1C
SP+0x20
41
Automatic Variables
Address Contents ;;;14 void static_auto_local( void )
SP aiG {
SP+4 aiF 000000 b50f PUSH {r0-r3,lr}
SP+8 aiE
;;;15 int aiB;
SP+0xC aiB
SP+0x10 r0 ;;;16 static int siC=3;
SP+0x14 r1 ;;;17 int * apD;
SP+0x18 r2 ;;;18 int aiE=4, aiF=5, aiG=6;
SP+0x1C r3 000002 2104 MOVS r1,#4
SP+0x20 lr
000004 9102 STR r1,[sp,#8]
000006 2105 MOVS r1,#5
▪ Initialize aiE 000008 9101 STR r1,[sp,#4]
00000a 2106 MOVS r1,#6
▪ Initialize aiF 00000c 9100 STR r1,[sp,#0]
▪ Initialize aiG …
;;;21 aiB = siC + siA;
…
▪ Store value for aiB 00001c 9103 STR r1,[sp,#0xc]
42
USING POINTERS
43
Using Pointers to Automatics
▪ C Pointer:
A variable which holds the data’s address.
44
Using Pointers to Statics
;;;24 apD = &siC;
▪ Load r0 with variable’s address from address of 000026 4833 LDR r0,|L1.244|
copy of variable’s address ;;;25 (*apD) += 9;
▪ Load r1 with variable’s value from memory 000028 6801 LDR r1,[r0,#0]
▪ Operate on r1 00002a 3109 ADDS r1,r1,#9
▪ Save back to variable’s address 00002c 6001 STR r1,[r0,#0]
|L1.244|
DCD ||siC||
AREA ||.data||, DATA, ALIGN=2
||siC||
DCD 0x00000003
45
CONTROL FLOW
51
Control Flow: Conditionals and Loops
▪ How does the compiler implement conditionals and loops?
1. Conditionals: if switch
if (x){ switch (x) {
y++; case 1:
} else { y += 3;
y--; break;
} case 31:
y -= 5;
break;
default:
y--;
break;
}
52
Control Flow: If/Else
if (x){
y++;
} else {
x is assumed in r1 and y in r2 y--;
}
;;;39 if (x){
000056 2900 CMP r1,#0
000058 d001 BEQ |L1.94|
;;;40 y++;
00005a 1c52 ADDS r2,r2,#1
00005c e000 B |L1.96|
|L1.94|
;;;41 } else {
;;;42 y--;
00005e 1e52 SUBS r2,r2,#1
|L1.96|
;;;43 }
53
Control Flow: Switch ;;;45
000060 2901
switch (x) {
CMP r1,#1
000062 d002 BEQ |L1.106|
000064 291f CMP r1,#0x1f
000066 d104 BNE |L1.114|
000068 e001 B |L1.110|
|L1.106|
;;;46 case 1:
;;;47 y += 3;
00006a 1cd2 ADDS r2,r2,#3
;;;48 break;
00006c e003 B |L1.118|
|L1.110|
;;;49 case 31:
;;;50 y -= 5;
00006e 1f52 SUBS r2,r2,#5
;;;51 break;
0x00006e 0x000072 0x00006a 000070 e001 B |L1.118|
|L1.114|
;;;52 default:
;;;53 y--;
000072 1e52 SUBS r2,r2,#1
;;;54 break;
000074 bf00 NOP
|L1.118|
0x000076
000076 bf00 NOP
;;;55 }
54
Iteration: For
|L1.140|
;;;62 x += i;
000084 18c9 ADDS r1,r1,r3
000086 1c5b ADDS r3,r3,#1;61
|L1.144|
000088 2b0a CMP r3,#0xa
;61
00008a d3fb BCC |L1.140|
;;;63 }
55
Iteration: Do While
;;;57 do {
000078 bf00 NOP
|L1.122|
;;;58 x += 2;
00007a 1c89 ADDS r1,r1,#2
;;;59 } while (x < 20);
00007c 2914 CMP r1,#0x14
56
Iteration: While <
57