Embedded Programming: Models,
Assembly, Linking, and Loading
Presenter: Dr. W Jino Hans, AsP/ECE
Session Outline
1 2
Introduction to Embedded Assembly Language Programming
Programming Models
Learn about the role of assembly language in
We will explore the various programming embedded systems and how it bridges high-level
approaches used in embedded systems and code and machine code.
understand their unique characteristics.
3 4
Linking Process Loading Process
Understand how multiple object files are combined Discover how programs are placed into memory
into a single executable program through linking. for execution in embedded systems.
Session Outcomes
After completing this session, you will be able to:
Understand Comprehend Apply Concepts to
Embedded Assembly, Linking, Development
Programming and Loading
Differentiate between high- Describe the assembly Recognise the significance
Models
level, assembly, and hybrid process, explain how of these processes in
programming models and linking resolves references embedded systems
identify which is between object files, and development and how they
appropriate for specific understand how programs impact performance,
embedded applications. are loaded into memory. memory usage, and
hardware interaction.
Embedded Programming Models Overview
Embedded systems programming can follow several
models, each with distinct advantages and limitations. High-level Model
The choice of model depends on project requirements,
Uses languages like C/C++; offers rapid
hardware constraints, and developer expertise.
These models represent different approaches to creating development and portability but less direct hardware
software for embedded systems, ranging from high-level control.
abstractions to direct hardware manipulation.
Assembly Model
Provides maximum control over hardware and
execution timing; ideal for performance-critical or
resource-constrained systems.
Hybrid Model
Combines high-level and assembly code to balance
development speed, maintainability, and
performance.
High-Level Language Model
Source Code Compiler Target System
Programs written in languages Translates high-level code into The compiled program runs on
like C, C++, or Python that assembly language specific to the embedded hardware with
provide abstraction from the target processor. some performance trade-offs.
hardware details.
• Faster development • •
cycle Optimizes code for Less precise timing control
• Better code readability performance or size • Compiler-dependent optimizations
• • Handles memory allocation •
Easier maintenance Suitable for most embedded
• Manages register usage applications
Assembly Language Model
Characteristics Advantages
• Direct representation of machine instructions in • Maximum performance optimization
human-readable form • Smallest possible code footprint
• One-to-one mapping between assembly instructions • Direct hardware access and control
and machine code
• Critical for real-time and interrupt-driven systems
• Precise control over CPU operations and timing
•
Disadvantages
Hardware-specific coding requiring deep knowledge of architecture
• Slower development time
• Difficult to maintain and debug
• Not portable across different processors
Assembly code is typically used for performance-critical sections, interrupt handlers, boot code, and device
drivers where timing and hardware control are essential.
Hybrid Model (Mixed Programming)
High-Level Code Assembly Code
Used for business logic, Used for hardware-specific
algorithms, and non-time-critical operations and time-critical
• functions sections
• Direct hardware access
Better abstraction and maintainability
• Faster development cycle 2 • Precise timing control
• Easier to read and debug • Maximum performance
Optimization Balance
Integration Methods
Strategic decisions on what to
Techniques to combine both code types
implement in which language
• Inline assembly in C/C++
• Performance profiling to
• Separate modules with defined
identify bottlenecks
interfaces
• Critical paths in assembly
• Compiler intrinsics
• Higher-level abstractions elsewhere
Compilation Process Refresher
Assembly
Compilation
Translates assembly code into
Preprocessing
Converts preprocessed source machine code (object files)
Expands macros, includes code into assembly language
• Instruction encoding
header files, and processes specific to the target
• Symbol table creation
conditional directives
• Text substitution architecture
operations • Syntax checking
• Relocatable object files (.o or .obj)
• Removal of comments • Code optimization
• Conditional compilation • Machine-dependent code
generation
This process creates multiple object files that need to be combined through linking before they can be executed on
Deep Dive: Assembly Language
Key Components Example Assembly Code (ARM)
• Mnemonics: Human-readable instruction codes
; Add two numbers and store result
(MOV, ADD, JMP)
MOV R0, #10 ; Load value 10 into R0
• Labels: Symbolic names for memory addresses
MOV R1, #25 ; Load value 25 into R1
• Directives: Instructions to the assembler, not the CPU ADD R2, R0, R1 ; Add R0 and R1, store in R2
• Operands: Data or addresses that instructions operate onSTR R2, [R3] ; Store result at address
• in R3
Comments: Documentation within code (often
prefixed with ;)
This simple code demonstrates how assembly
languages use mnemonics (MOV, ADD, STR) to
represent machine instructions in a readable
format, while still providing direct control over
registers and memory operations.
Linking: Creating Executables
Purpose of Linking Symbol Resolution
The linker combines multiple object files and The linker resolves references to functions and
libraries into a single executable program, variables defined in different object files,
resolving all references between them. ensuring all symbols are defined exactly once.
Memory Allocation Relocation
Assigns specific memory addresses to code and Adjusts memory references in the code to
data sections, creating a complete memory map account for the actual addresses where code
for the program. and data will be placed in memory.
Linking is crucial in embedded systems as it allows modular development and efficient memory organization,
especially important in resource-constrained environments.
Linking: Static vs Dynamic
Static Linking Dynamic Linking
All code is incorporated into the executable at build [Link] code is linked at runtime from shared libraries.
• Produces self-contained executables • Smaller executable size
• No external dependencies at runtime • Memory sharing between applications
• Larger file size (includes all library code) • Easier updates (replace library without rebuilding)
• Better predictability in embedded systems • Additional runtime overhead
• Commonly used for safety-critical applications • Less common in small embedded systems
Most resource-constrained embedded systems prefer static linking for deterministic behavior and
simplicity, while more complex systems like embedded Linux may use dynamic linking for
flexibility and resource sharing.
Loading: Program Into Memory
Initial Bootup 1
tloader initializes hardware and prepares system for program execution.
2 Memory Allocation
Loader allocates RAM for program code, data, stack, and heap
according to the executable's requirements.
Image Transfer 3
Program image is copied from storage (flash, EEPROM) into
RAM at specified addresses.
4 Relocation Adjustments
If needed, addresses are adjusted to match actual loading
location (position-independent code may not require this).
Initialization 5
Global variables are initialized, runtime environment is set up,
and startup code is executed.
6 Execution Transfer
Control is transferred to the program's entry point (often
main() function) to begin execution.
Memory Placement in Embedded System
Memory Map Organization Strategic Placement Considerations
Embedded systems require careful memory • Memory-mapped I/O registers at fixed addresses
organization to ensure proper operation: • Interrupt vectors at specific locations
• Code section (Flash/ROM) - Contains executable • Critical code in faster memory
instructions • Alignment requirements for certain processors
• Data section (RAM) - Contains initialized variables • Separation of code and data for security
• BSS section (RAM) - Contains uninitialized variables • Cache optimization through memory layout
• Stack (RAM) - For function calls and local variables
• Heap (RAM) - For dynamic memory allocation
Memory placement is controlled through linker scripts that define the exact memory layout, crucial for
hardware interaction and performance optimization.
Example: Compilation to Execution Workflow
Source Files
main.c, utils.c, driver.c, startup.s
Compilation
2 gcc -c main.c utils.c driver.c
as -o startup.o startup.s
Linking
ld -T [Link] main.o utils.o driver.o startup.o -o [Link]
Binary Generation
objcopy -O binary [Link] [Link]
Loading
5
Bootloader or programmer loads [Link] into device memory
This workflow illustrates the complete process from source code to running program. The linker script ([Link]) is particularly important as it defines the memory
layout specific to the target embedded device.
Program Design and Analysis
This presentation explores software components, program representations, and implementation techniques used in
computer systems. We'll examine state machines, circular buffers, filters, and program models that help us
understand and optimize code.
Overview
Software Components Program Representations Assembly and Linking
Building blocks that make up Ways to model and visualize Converting high-level code to
complex systems code structure executable programs
Software State Machines
Key Characteristics Common Applications
• Maintains internal state as a variable • Control-dominated code
• Changes state based on inputs • Reactive systems
• Follows predefined transition rules • User interfaces
• Protocol implementations
State Machine Example
This state machine models a car seat belt warning system with four states: IDLE, SEATED, BELTED, and BUZZER.
Transitions occur based on sensor inputs (seat occupied, belt fastened) and timer events.
C Implementation of State Machine
#define IDLE 0
#define SEATED 1
#define BELTED 2
#define BUZZER 3
switch (state)
{ case IDLE:
if (seat) {
state = SEATED;
timer_on = TRUE;
}
break;
case SEATED:
if (belt)
state = BELTED;
else if (timer)
state = BUZZER;
break;
// Other cases...
}
The switch statement implements the state transitions based on current state and input conditions.
Array-Based Queue in C
Queue Definition Enqueue Operation Dequeue Operation
#define Q_SIZE 5 void enqueue(int val) { int dequeue() {
#define Q_MAX (Q_SIZE - 1) // Check if the queue is int returnval;
full // Check if the queue is empty
int q[Q_SIZE]; if (((tail + 1) % Q_SIZE) == if (head == tail)
int head, tail; head) error("empty queue", head);
error("queue full", // Get the value at the head
void queue_init() { tail); position
head = 0; // Insert value at the returnval = q[head];
tail = 0; current tail position // Move head pointer circularly
} q[tail] = val; if (head == Q_MAX)
// Update tail pointer head = 0;
(circularly) else
if (tail == Q_MAX) head++;
tail = 0;
else return returnval;
tail++; }
Producer-Consumer Systems
Key Characteristics
• Queues allow varying input and output rates
• Producers generate data
Common in operating systems, networking, and
• Consumers process data
multimedia applications
• Buffer decouples timing requirements
Program Representation Models
Source code is not a good representation for programs: it's clumsy and leaves much information implicit.
Data Flow Graph (DFG) Control-Data Flow Single Assignment Form
Graph (CDFG)
Models data dependencies Each variable is assigned
between operations, showing Represents both control flow exactly once, making data
the minimal ordering and data dependencies in a dependencies explicit
requirements program
Compilers derive these intermediate representations to manipulate and optimize programs.
Data Flow Graphs
Single Assignment Form Resulting DFG
Original Basic Block Single Assignment Form
x = a + b; x = a + b;
y = c - d; y = c - d;
z = x * y; z = x * y;
y = b + d; y1 = b + d;
Converting to single assignment form makes data dependencies explicit.
Control-Data Flow Graphs
CDFG Components
• Decision nodes (control)
• Data flow nodes (computation)
• Edges showing flow between nodes
CDFGs represent complex control structures like if-else statements,
switch cases, and loops.
Example: CDFG for if-else and switch statements
Session Summary & Test Your Understanding
Key Takeaways Test Your Understanding
• Embedded systems use high-level, assembly, or hybrid 1. Why is assembly language still used in modern embedded syste
programming models depending on requirements 2. What is the primary purpose of the linking process?
• Assembly language provides direct hardware control but 3. Compare and contrast static versus dynamic linking in
at the cost of development time embedded contexts.
• Linking combines multiple object files and resolves cross-references
4. Describe the complete workflow from source code to
• Loading places the executable into memory and execution in an embedded system.
prepares it for execution 5. How does memory placement affect embedded system performa
• Memory organization is critical for embedded systems performance