You are on page 1of 50

C as Implemented in

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 following points should be clear to the embedded system developer:

➢ 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)

➢ How the C program interfaces with an assembly function

➢ How to include assembly instructions in a C program

➢ How the program handles interrupts


3
C or Assembly
C Assembly
Easier to write code Difficult

Faster in developing applications Longer time-to-market

Easier to read, understand & change code Difficult to maintain assembly code

Portable (mostly) Not portable

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

Minimum run time not guaranteed Optimized run time

So, use C to develop large applications, and learn assembly to:


• write code when execution time is critical, and compact code size is essential
• Analyze, debug, and enhance the code resulting from a C program compilation
4
The C Program
void B(void) {
..
➢ A C program is made of one or more functions .
main }

➢ The main () function is required in every C program. void J(void) {


..
J K .
B();
..
➢ Running the program consists of running the main .
}
function. B
void K(void) {
Function call graph example ..
➢ The main function for embedded systems software .
never completes. }

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

After performing these steps, the CPU can start


executing the code in main.

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.

EEPROM: Dynamic RAM (DRAM):


Erased and reprogrammed electrically one location at a
Needs periodic refresh pulses.
time. Used for configuration data (small size)

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.

➢ Will program only read this data? (constants)


This read only data need to be placed in ROM, EEPROM, or Flash.

➢ Will program change this data? (variables)


This read/write data need to be placed in RAM.

➢ 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

What goes where?


▪ Code is obvious → Flash ROM
▪ And the others?

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

signed char int8_t 8 Signed -128 .. 127


unsigned short uint16_t 16 Unsigned 0 .. 65,535
short int16_t 16 Signed -32,768 .. 32,767
unsigned int uint32_t 32 Unsigned 0 .. 4,294,967,295
int int32_t 32 Signed -2,147,483,648 .. 2,147,483,647
unsigned long long uint64_t 64 Unsigned 0 .. 18,446,744,073,709,551,615
long long int64_t 64 Signed -9,223,372,036,854,775,808 ..
9,223,372,036,854,775,80
Floating Point

C type IEE754 Name Bits Range


Data Types

By default, variables are considered as


float Single Precision 32 -3.4E38 .. 3.4E38
signed unless the unsigned keyword is used,
with the exception of char which is compiler
double Double Precision 64 -1.7E308 .. 1.7E308 dependent.

Native data type:


Primary data type used by ALU and registers.
int defines a number with a precision that for cores other than ARM Cortex_M, will vary depending on the core
12 and the compiler.
Variable Declaration
A variable declaration includes: int i, j, k; /*name and type. * /
1. Type
2. Name (identifier) char cx, cy; /*name and type. */
3. Initial value (optional). int m = 0; /*name, type, and initial value.*/
char echo = ‘y’; /*name, type, and initial value. */
Native data type:
Primary data type used by ALU and registers.
int Defines a number with a precision that will vary from compiler to compiler.
(32-bit integer for ARM Cortex-M CPUs).

Qualifiers short and long can be applied to integers. For CW C compiler:


• short is 16 bits Ex: short int i (default for CW C compiler)
• long is 32 bits Ex: long int i (i is stored in 32 bits)

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:

Integers A constant like 1234 is an int.


A long constant is written with a terminal l or L, as in 44332211L

Characters One character within single quotes such as ‘x’ is represented by


the ASCII code of the character
Strings A sequence of characters surrounded by double quotes such as
“Hello”, or “” for empty string

float A 32-bit single-precision floating-point number

double A 64-bit double-precision floating-point number

The base of a number is specified by a prefix to the number:


hexadecimal 0x 0x45
octal o o1234
Decimal No prefix 1234

Example: const unsigned char key=0x23;


14
Program Memory Use
How long does the data need to exist?
Reuse memory if possible.
int a, b;
const char c=123; ▪ Statically allocated
int d=31;
◦ Exists from program start to end
void main(void) {
◦ Each variable has its own fixed location
int e;
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
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.

• A function may call other functions

➢ To execute a function:

1) Pass the arguments

2) Call the function


Usually as subroutine with branch link (bl) or branch link and exchange instruction (blx)

19
Passing Arguments
▪ How to pass them?
Much faster to use registers than stack
Not always feasible because quantity of registers is
limited.

▪ Basic rules Example:


A function arguments: (char x, int y, double z):
1. Process arguments in order they appear in source code
x is extended to 32 bits and passed in r0
2. Round size up to be a multiple of 4 bytes y is passed in r1
3. Copy arguments into core registers (r0-r3), aligning z is passed in r2 and r3
doubles to even registers Changing the arguments order: (char x , double z, int y)
4. Copy remaining arguments onto stack, aligning doubles to x is extended to 32 bits and passed in r0
even addresses z is passed in r2 (even register) and r3 (not r1 and r2)
y is passed on stack

Specific rules in AAPCS, Section 5.5

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.

Registers used for passing


Return value size Fundamental Composite
Data Type Data Type
1-4 bytes r0 r0
8 bytes r0-r1 stack
16 bytes r0-r3 stack
Indeterminate size n/a stack
21
Function Call Example
int fun2(int a1, int a2) {
int i;
a2 += fun3(a1, 4, 5, 6);
… fun2 PROC
} ;;;85 int fun2(int a1, int a2) {
...
• Argument 4 into r3 0000e0 2306 MOVS r3,#6
• Argument 3 into r2 0000e2 2205 MOVS r2,#5
• Argument 2 into r1 0000e4 2104 MOVS r1,#4
• Argument 0 into r0 0000e6 4630 MOV r0,r6

• Call fun3 with BL instruction 0000e8 f7fffffe BL fun3

• 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.

1. Body: Performs work specified by the function source code.


A function’s P&E are responsible for creating and
destroying its activation record.
2. Epilog: Final code in the function which: Remember AAPCS:
‒ Restores register. Scratch registers r0-r3 are not expected to be
‒ Prepares the return value (if any) preserved upon returning from a called
subroutine, can be overwritten.
‒ Frees activation record Preserved (“variable”) registers r4-r8, r10-r11
‒ Returns control to the calling function. must have their original values upon returning
from a called subroutine.

25
Return Address
▪ Return address stored in LR by bl, blx instructions

▪ Consider case where a() calls b() which calls c()


▪ On entry to b(), LR holds return address in a()
▪ When b() calls c(), LR will be overwritten with return address in b()

▪ After c() returns, b() will have lost its return address

▪ Does this function call a subroutine?


▪ Yes: must save and restore LR on stack just like other preserved registers, but LR value is popped into PC
rather than LR
▪ No: don’t need to save or restore LR, as it will not be modified

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 ...

;;;106 return a+b+c;


▪ Compute return value, placing in return 00011c 1858 ADDS r0,r3,r1
register r0 00011e 1880 ADDS r0,r0,r2
;;;107 }
▪ Deallocate 32 bytes from stack 000120 b008 ADD sp,sp,#0x20

▪ Pop r4 (preserved register) and PC 000122 bd10 POP {r4,pc}


(return address) ENDP

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.

Make it easier to create modular, isolated and integrated code.

▪ 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)

record Activation record Local storage ← SP


for current function Return address
▪ Returning from a function deallocates f4 Arguments
the activation record Local storage
Activation record
Return address
▪ Automatic variables and housekeeping for function f3
Arguments
information are stored in a function’s Local storage
activation record Activation record
Return address
for functionf2
Arguments Example call stack:
▪ Not all fields (LS, RA, Arg) may be Higher Local storage Function f1 called function
present for each activation record. address Activation record
Return address f2 which called function f3
for function f1
which called function f4.
Call stack: Arguments

Stack of activation records/stack frames of functions which have


started executing but have not yet completed
33
ACCESSING DATA IN MEMORY

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

▪ Load the pointer into a register (r0)

▪ Can now load variable’s value into a register (r1) from memory
using that pointer in r0

▪ Similarly, we can store a new value to the variable in memory. Variable

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.

▪ aiB is on stack at SP+0xc

;;;22 apD = & aiB;


▪ Compute r0 with variable’s address from stack 00001e a803 ADD r0,sp,#0xc
pointer and offset (0xc)
;;;23 (*apD)++;
▪ Load r1 with variable’s value from memory 000020 6801 LDR r1,[r0,#0]
▪ Operate on r1 000022 1c49 ADDS r1,r1,#1
▪ save back to variable’s address 000024 6001 STR r1,[r0,#0]

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;
}

2. Loops: for while do while


for (i = 0; i < 10; i++){ while (x<10) { do {
x += i; x = x + 1; x += 2;
} } } while (x < 20)

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

;;;61 for (i = 0; i < 10; i++){


000080 2300 MOVS r3,#0
000082 e001 B |L1.144|

|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

00007e d3fc BCC |L1.122|

|L1.122| = address 00007a

56
Iteration: While <

;;;61 while (x<10) {


000080 e000 B |L1.132|
|L1.130|
;;;62 x = x + 1;
000082 1c49 ADDS r1,r1,#1
|L1.132|
000084 290a CMP r1,#0xa ;57
000086 d3fc BCC |L1.130|
;;;63 }

|L1.132| = address 000084


|L1.130| = address 000082

57

You might also like