Proc Emb Ch4
Proc Emb Ch4
Assembly Language
1
Overview
2
Compiler Stages
Parser
reads in C code,
checks for syntax errors,
forms intermediate code (tree representation)
High-Level Optimizer
Modifies intermediate code (processor-independent)
Code Generator
Creates assembly code step-by-step from each node of the intermediate code
Allocates variable uses to registers
Low-Level Optimizer
Modifies assembly code (parts are processor-specific)
Assembler
Creates object code (machine code)
Linker/Loader
Creates executable image from object file
3
Examining Assembly Code before Debugger
4
Examining Disassembled Program in Debugger
5
A Word on Code Optimizations
These optimizations often get in way of understanding what the code does
Fundamental trade-off: Fast or comprehensible code?
Compiler optimization levels: Level 0 to Level 3
Code examples here may use “volatile” data type modifier to reduce compiler
optimizations and improve readability
6
USING REGISTERS
7
Register Use Conventions
Scratch registers are not expected to be preserved upon returning from a called
subroutine
r0-r3
Preserved (“variable”) registers are expected to have their original values upon
returning from a called subroutine
r4-r8, r10-r11
8
Core Register Use
Register Synonym Special Role in the procedure call standard
r15 PC The Program Counter.
r14 LR The Link Register.
r13 SP The Stack Pointer.
r12 IP The Intra-Procedure-call scratch register.
Must be saved, restored by
r11 v8 Variable-register 8.
callee-procedure it may modify
r10 v7 Variable-register 7. them.
Platform register. The meaning of this register is defined
r9 v6,SB,TR
by the platform standard.
r8 v5 Variable-register 5. Must be saved, restored by
r7 v4 Variable register 4. callee-procedure it may modify
r6 v3 Variable register 3. them.
Calling subroutine expects
r5 v2 Variable register 2.
these to retain their value.
r4 v1 Variable register 1.
r3 a4 Argument / scratch register 4.
Don’t need to be saved. May be
r2 a3 Argument / scratch register 3. used for arguments, results, or
r1 a2 Argument / result / scratch register 2. temporary values.
r0 a1 Argument / result / scratch register 1.
9
MEMORY REQUIREMENTS
10
What Memory Does a Program Need?
int a, b;
Five possible types
const char c=123; Code
int d=31; Read-only static data
void main(void) {
Writable static data
int e;
◦ Initialized
char f[32];
e = d + 7; ◦ Zero-initialized
a = e + 29999; ◦ Uninitialized
strcpy(f,“Hello!”); Heap
} Stack
What goes where?
Code is obvious
And the others?
11
What Memory Does a Program Need?
int a, b;
Can the information change?
const char c=123; No? Put it in read-only, nonvolatile memory
int d=31; ◦ Instructions
void main(void) { ◦ Constant strings
int e; ◦ Constant operands
char f[32]; ◦ Initialization values
e = d + 7;
Yes? Put it in read/write memory
a = e + 29999;
strcpy(f,“Hello!”); ◦ Variables
} ◦ Intermediate computations
◦ Return address
◦ Other housekeeping data
12
What Memory Does a Program Need?
int a, b;
How long does the data need to exist? Reuse
const char c=123; memory if possible.
int d=31; Statically allocated
void main(void) { ◦ Exists from program start to end
int e;
◦ Each variable has its own fixed location
char f[32];
◦ Space is not reused
e = d + 7;
a = e + 29999; Automatically allocated
strcpy(f,“Hello!”); ◦ Exists from function start to end
} ◦ Space can be reused
Dynamically allocated
◦ Exists from explicit allocation to explicit deallocation
◦ Space can be reused
13
Program Memory Use
RAM Flash ROM
int a, b;
Zero-Initialized Data const char c=123; Constant Data
int d=31;
void main(void) {
int e;
Initialized Data InitializationData
char f[32];
e = d + 7;
a = e + 29999;
Stack strcpy(f,“Hello!”); Startup and Runtime
} Library Code
14
Activation Record
Activation records are located Lower
(Free stack space)
on the stack address
Local storage <- Stack ptr
Calling a function creates Activation record for
Return address
an activation record current function
Arguments
Returning from a function Local storage
Activation record for
deletes the activation record caller function
Return address
Arguments
Local storage
Activation record for
Automatic variables and caller’s caller function
Return address
housekeeping information are Arguments
Higher Activation record for Local storage
stored in a function’s activation address caller’s caller’s caller Return address
record function Arguments
Not all fields (LS, RA, Arg) may be present for each activation record
15
Type and Class Qualifiers
Const
Never written by program, can be put in ROM to save RAM
Volatile
Can be changed outside of normal program flow: ISR, hardware register
Compiler must be careful with optimizations
Static
Declared within function, retains value between function invocations
Scope is limited to function
16
Linker Map File
17
C Run-Time Start-Up Module
RAM Flash ROM
After reset, MCU must…
Zero-Initialized Data
Fill with Initialization Data
a, b zeros 31
Initialize hardware
Peripherals, etc. Initialized Data Constant Data
Set up stack pointer d c: 123
Hello!
18
ACCESSING DATA IN MEMORY
19
Accessing Data
int siA;
void static_auto_local() {
int aiB;
What does it take to get at a variable static int siC=3;
in memory? int * apD;
Depends on location, which depends on int aiE=4, aiF=5, aiG=6;
storage type (static, automatic, dynamic) siA = 2;
aiB = siC + siA;
apD = & aiB;
(*apD)++;
apD = &siC;
(*apD) += 9;
apD = &siA;
apD = &aiE;
apD = &aiF;
apD = &aiG;
(*apD)++;
aiE+=7;
*apD = aiE + aiF;
}
20
Static Variables
Static var can be located anywhere in 32-bit Load r0 with pointer to variable
Load r1 from [r0]
memory space, so need a 32-bit pointer Use value of variable
Can’t fit a 32-bit pointer into a 16-bit
Label:
instruction (or a 32-bit instruction), so save 32-bit pointer to Variable
the pointer separate from instruction, but
nearby so we can access it with a short PC-
relative offset
Load the pointer into a register (r0)
Can now load variable’s value into a register
(r1) from memory using that pointer in r0
Variable
Similarly can store a new value to the variable
in memory
21
Static Variables AREA ||.text||, CODE, READONLY, ALIGN=2
;;;20 siA = 2;
00000e 2102 MOVS r1,#2 ; r1 = 2
000010 4a37 LDR r2,|L1.240| ; r2 = &siA
Key 000012 6011 STR r1,[r2,#0] ; *r2 = r1
variable’s value
variable’s address ;;;21 aiB = siC + siA;
000014 4937 LDR r1,|L1.244| ; r1 = &siC
address of copy of variable’s
000016 6809 LDR r1,[r1,#0] ; r1 = *r1
address 000018 6812 LDR r2,[r2,#0] ; r2 = *r2
Addresses of siA and siC are 00001a 1889 ADDS r1,r1,r2 ; r1 = r1 + r2
...
stored as literals to be loaded
into pointers |L1.240|
Variables siC and siA are located DCD ||siA||
|L1.244|
in .data section with initial values DCD ||siC||
AREA ||.data||, DATA, ALIGN=2
||siC||
DCD 0x00000003
||siA||
DCD 0x00000000
22
Automatic Variables Stored on Stack
int main(void) {
Automatic variables are stored in a function’s auto vars;
a();
activation record (unless optimized and promoted }
to register)
void a(void) {
Activation records are located on the stack auto vars;
Calling a function creates an activation record, b();
allocating space on stack }
24
Automatic Variables
Address Contents
SP aiG ;;;14 void static_auto_local( void ) {
SP+4 aiF 000000 b50f PUSH {r0-r3,lr}
SP+8 aiE ;;;15 int aiB;
SP+0xC aiB ;;;16 static int siC=3;
SP+0x10 r0 ;;;17 int * apD;
SP+0x14 r1 ;;;18 int aiE=4, aiF=5, aiG=6;
SP+0x18 r2 000002 2104 MOVS r1,#4
SP+0x1C r3 000004 9102 STR r1,[sp,#8]
SP+0x20 lr
000006 2105 MOVS r1,#5
000008 9101 STR r1,[sp,#4]
Initialize aiE 00000a 2106 MOVS r1,#6
Initialize aiF 00000c 9100 STR r1,[sp,#0]
…
Initialize aiG ;;;21 aiB = siC + siA;
…
00001c 9103 STR r1,[sp,#0xc]
Store value for aiB
25
USING POINTERS
26
Using Pointers to Automatics
27
Using Pointers to Statics
;;;24 apD = &siC;
Load r0 with variable’s address from 000026 4833 LDR r0,|L1.244|
address of copy of variable’s address ;;;25 (*apD) += 9;
000028 6801 LDR r1,[r0,#0]
00002a 3109 ADDS r1,r1,#9
Load r1 with variable’s value from 00002c 6001 STR r1,[r0,#0]
memory |L1.244|
DCD ||siC||
AREA ||.data||, DATA, ALIGN=2
Operate on r1, save back to variable’s ||siC||
address DCD 0x00000003
28
ARRAY ACCESS
29
Array Access
uint8 buff2[3];
What does it take to get at an uint16 buff3[5][7];
array element in memory?
Depends on how many dimensions uint32 arrays(uint8 n, uint8 j) {
Depends on element size and row volatile uint32 i;
width i = buff2[0] + buff2[n];
i += buff3[n][j];
Depends on location, which
return i;
depends on storage type (static,
}
automatic, dynamic)
30
Accessing 1-D Array Elements
Address Contents
Need to calculate element address: sum of… buff2 buff2[0]
array start address
buff2 + 1 buff2[1]
offset: index * element size
buff2 + 2 buff2[2]
buff2 is array of unsigned characters
31
Accessing 2-D Array Elements
uint16 buff3[5][7]
Address Contents var[rows][columns]
buff3 buff3[0][0]
Sizes
buff3+1
Element: 2 bytes
buff3+2 buff3[0][1]
buff3+3 Row: 7*2 bytes = 14 bytes (0xe)
(etc.) Offset based on row index and column
buff3+10 buff3[0][5] index
buff3+11 column offset = column index *
buff3+12 buff3[0][6] element size
buff3+13
row offset = row index * row size
buff3+14 buff3[1][0]
buff3+15
buff3+16 buff3[1][1]
buff3+17
(etc.)
buff3+68 buff3[4][6]
buff3+69
32
Code to Access 2-D Array
Instruction r0 r1 r2 r3 r4 Description
;;; i += buff3[n][j]; i j n - -
MOVS r3,#0xe - - - 0xe - Load row size
MULS r3,r2,r3 - - n n*0xe - Multiply by row number
LDR r4,|L1.276| - - - - &buff3 Load address of buff3
ADDS r3,r3,r4 - - - &buff3+n*0xe - Add buff3 address to row
offset
LSLS r4,r1,#1 - j - - j<<1 Multiply column number by 2
(buff3 is uint16 array)
LDRH r3,[r3,r4] - - - *(uint16)(&buff3+n*0xe+j<<1) j<<1 Load halfword r3 with
= buff3[n][j] element at r3+r4 (buff3 +
row offset + col offset)
ADDS r0,r3,r0 i+buff3[n][j] - - buff3[n][j] Add r3 to r0 (i)
33
CALLING FUNCTIONS
34
AAPCS Core Register Use
Register Synonym Special Role in the procedure call standard
r15 PC The Program Counter.
r14 LR The Link Register.
r13 SP The Stack Pointer.
r12 IP The Intra-Procedure-call scratch register.
r11 v8 Variable-register 8.
r10 v7 Variable-register 7.
Platform register. The meaning of this register is defined
r9 v6,SB,TR
by the platform standard.
r8 v5 Variable-register 5.
r7 v4 Variable register 4.
r6 v3 Variable register 3.
r5 v2 Variable register 2.
r4 v1 Variable register 1.
r3 a4 Argument / scratch register 4.
r2 a3 Argument / scratch register 3.
r1 a2 Argument / result / scratch register 2.
r0 a1 Argument / result / scratch register 1.
35
Function Arguments and Return Values
36
Return Values
37
Call Example
int fun2(int arg2_1, int arg2_2) { fun2 PROC
int i; ;;;85 int fun2(int arg2_1, int
arg2_2 += fun3(arg2_1, 4, 5, 6); arg2_2) {
… ...
} 0000e0 2306 MOVS r3,#6
0000e2 2205 MOVS r2,#5
Argument 4 into r3 0000e4 2104 MOVS r1,#4
Argument 3 into r2 0000e6 4630 MOV r0,r6
Argument 2 into r1
Argument 0 into r0 0000e8 f7fffffe BL fun3
Call fun3 with BL instruction
0000ec 1904 ADDS r4,r0,r4
Result was returned in r0, so add to
r4 (arg2_2 += result)
38
Call and Return Example
fun3 PROC
int fun3(int arg3_1, int arg3_2, ;;;81 int fun3(int arg3_1, int arg3_2,
int arg3_3, int arg3_4) { int arg3_3, int arg3_4) {
return arg3_1*arg3_2*
arg3_3*arg3_4; 0000ba b510 PUSH {r4,lr}
}
39
CONTROL FLOW
40
Control Flow: Conditionals and Loops
41
Control Flow: If/Else
;;;39 if (x){
000056 2900 CMP r1,#0
000058 d001 BEQ |L1.94|
T F ;;;40 y++;
00005a 1c52 ADDS r2,r2,#1
Condition 00005c e000 B |L1.96|
|L1.94|
;;;41 } else {
action_if action_else ;;;42 y--;
00005e 1e52 SUBS r2,r2,#1
|L1.96|
;;;43 }
42
Control Flow: Switch 000066 d104 BNE |L1.114|
000068 e001 B |L1.110|
Evaluate |L1.106|
;;;46 case 1:
;;;47 y += 3;
T 00006a 1cd2 ADDS r2,r2,#3
= const1? action1 ;;;48 break;
00006c e003 B |L1.118|
F |L1.110|
T ;;;49 case 31:
= const2? action2 ;;;50 y -= 5;
00006e 1f52 SUBS r2,r2,#5
F ;;;51 break;
000070 e001 B |L1.118|
action3 |L1.114|
;;;52 default:
;;;53 y--;
000072 1e52 SUBS r2,r2,#1
;;;54 break;
;;;45 switch (x) { 000074 bf00 NOP
000060 2901 CMP r1,#1 |L1.118|
000062 d002 BEQ |L1.106| 000076 bf00 NOP
000064 291f CMP r1,#0x1f ;;;55 }
43
Iteration: While
44
Iteration: For
;;;61 for (i = 0; i < 10; i++){
init_expression 000080 2300 MOVS r3,#0
000082 e001 B |L1.136|
|L1.132|
loop_body ;;;62 x += i;
000084 18c9 ADDS r1,r1,r3
000086 1c5b ADDS r3,r3,#1
cond_expression ;61
|L1.136|
000088 2b0a CMP r3,#0xa
T ;61
Condition
00008a d3fb BCC |L1.132|
;;;63 }
F
45
Iteration: Do/While
;;;65 do {
00008c bf00 NOP
loop_body
|L1.142|
;;;66 x += 2;
T 00008e 1c89 ADDS r1,r1,#2
Condition ;;;67 } while (x < 20);
000090 2914 CMP r1,#0x14
000092 d3fc BCC |L1.142|
F
46