Experiment 1: Assembly Basics and Program Structure β
Complete Lab Manual
For the complete experiment including learning objectives, theoretical background, and detailed explanations, download the PDF manual: Download Experiment 1 PDF
Learning Objectives β
After completing this experiment, you will be able to:
- Identify the main components of the ARM Cortex-M4 architecture, including general-purpose registers, stack pointer, link register, program counter, and program status register (xPSR).
- Write, assemble, and debug a minimal ARM assembly program containing a vector table and
Reset_Handler. - Use core data-processing, shift/rotate, and compare/test instructions to manipulate register data.
- Apply conditional execution and branching using condition codes (
EQ,NE,GT,LT, etc.). - Debug assembly programs in Keil uVision5 using breakpoints, single-stepping, and register/memory inspection to analyze instruction effects.
Experiment Overview β
This experiment introduces ARM Cortex-M4 assembly programming fundamentals, including register architecture, status flags, and memory organization. You will build minimal startup code with a vector table and Reset_Handler, practice data-processing and control-flow instructions, and use the Keil Β΅Vision5 debugger to single-step through code while inspecting registers and memory. By the end of this lab, you will understand the core building blocks of ARM assembly programming and be able to write, assemble, and debug low-level embedded code.
Theoretical Background β
Cortex-M4 Architecture β
Registers Overview β
The Cortex-M4 architecture includes a set of general-purpose registers (R0-R12), a stack pointer (SP), a link register (LR), a program counter (PC), and a program status register (xPSR), all of which are 32-bit registers. The general-purpose registers are used for data manipulation and temporary storage during program execution. The SP is used to manage the call stack, while the LR holds the return address for function calls. The PC points to the next instruction to be executed, and the xPSR contains flags and status information about the processor state.
Program Status Register (xPSR) holds the current state of the processor, including condition flags (Negative, Zero, Carry, Overflow), interrupt status, and execution state. These flags are updated based on the results of arithmetic and logical operations, allowing for conditional branching and decision-making in programs.
Memory Mapping β
The Cortex-M4 uses a flat memory model, where all memory locations are accessible through a single address space. This model simplifies programming and allows for efficient access to data and instructions. The memory is divided into several regions, including code memory (for storing instructions), data memory (for storing variables), and peripheral memory (for interfacing with hardware components). The architecture supports both little-endian and big-endian data formats, with little-endian being the default.
| Region | Address Range | Description |
|---|---|---|
| Code | 0x00000000β0x1FFFFFFF | Flash memory for program code |
| SRAM | 0x20000000β0x3FFFFFFF | On-chip static RAM for data |
| Peripheral | 0x40000000β0x5FFFFFFF | Memory-mapped peripheral registers |
| External RAM | 0x60000000β0x9FFFFFFF | External RAM (if implemented) |
| External Device | 0xA0000000β0xDFFFFFFF | External devices/memory (if implemented) |
| Private Peripheral Bus | 0xE0000000β0xE00FFFFF | Cortex-M4 internal peripherals (NVIC, SysTick, MPU, SCB) |
| System | 0xE0100000β0xFFFFFFFF | System region (reserved/system-level) |
Assembly Language Basics β
Assembly language is a low-level programming language that provides a direct correspondence between human-readable instructions and the machine code executed by the processor. Each instruction encodes a specific operation, such as moving data, performing arithmetic or logic, or altering control flow. Because it maps so closely to hardware, assembly allows precise control of system resources and is commonly used in performance-critical routines or when direct access to hardware is required.
Assembly programs are typically composed of three main elements: instructions, directives, and labels.
Instructions are the executable commands that the CPU carries out. Examples include data movement (MOV), arithmetic (ADD, SUB), logical operations (AND, ORR), and control flow (B, BL). Each instruction directly translates to one or more machine code opcodes and determines the actual behavior of the program.
Directives are commands to the assembler that guide how source code is translated into machine code but do not generate instructions themselves. Common examples include AREA (define a code or data section), ALIGN (align data to memory boundaries), DCD (allocate and initialize a word of storage), and EXPORT (export a symbol for linking). Directives organize program layout, control memory allocation, and manage symbol visibility.
Labels are symbolic names that mark specific locations in code or data. They act as targets for jumps and branches or as references for data access. Labels improve program readability and maintainability by avoiding hard-coded addresses.
Instruction Set Overview β
The ARM Cortex-M4 instruction set is a subset of the ARMv7-M architecture, designed for efficient execution in embedded systems. It includes a variety of instructions for data processing, memory access, and control flow. Key categories of instructions include:
- Data Processing Instructions: These include arithmetic operations (e.g.,
ADD,SUB), logical operations (e.g.,AND,ORR), and data movement instructions (e.g.,MOV,MVN). - Load and Store Instructions: Instructions like
LDR(load register) andSTR(store register) are used to transfer data between registers and memory. - Branch Instructions: Control flow is managed using branch instructions such as
B(branch),BL(branch with link), and conditional branches likeBEQ(branch if equal). - Special Instructions: These include instructions for system control, such as
NOP(no operation),WFI(wait for interrupt), and instructions for manipulating the stack and handling exceptions.
General Instruction Format β
Assembly source lines generally follow this shape:
[label] OPCODE{<cond>}{S} operands ; commentwhere curly braces {} denote optional components, and:
label: optional symbolic name marking the current address.OPCODE: instruction mnemonic (e.g.,ADD,MOV,B).<cond>: optional condition code (e.g.,EQ,NE,LT,GE) that predicates execution.S: optional suffix indicating whether to update the condition flags (e.g.,ADDS).operands: registers, immediates, or memory operands (e.g.,R0, R1, #1or[R2]).- Anything after a semicolon (
;) is a comment ignored by the assembler.
Example:
loop_start ADDS R0, R0, #1 ; R0 = R0 + 1, update flags (N,Z,C,V)Basic Program Template (Boilerplate) β
The minimal skeleton below shows a valid vector table in a READONLY RESET area, a READWRITE data area for variables, and a code area with the Reset_Handler entry point.
AREA RESET, CODE, READONLY ; Vector table lives in read-only code
EXPORT __Vectors ; Make symbol visible to the linker
__Vectors
DCD 0x20001000 ; Initial SP value (top of stack in SRAM)
DCD Reset_Handler ; Reset vector: entry address
ALIGN
; -------------------- Read-Write Data --------------------
AREA M_DATA, DATA, READWRITE ; Variables go here (RAM)
EXPORT COUNT ; Export if referenced by other modules
COUNT DCD 0 ; Initialized RW variable (word)
BUF SPACE 16 ; Uninitialized RW buffer (16 bytes)
ALIGN
; -------------------- Application Code -------------------
AREA MYCODE, CODE, READONLY
ENTRY
EXPORT Reset_Handler
Reset_Handler
; Example: COUNT++ and store to BUF[0]
LDR R0, =COUNT ; R0 <- &COUNT
LDR R1, [R0] ; R1 <- COUNT
ADDS R1, R1, #1 ; R1 = R1 + 1 (update flags)
STR R1, [R0] ; COUNT <- R1
LDR R2, =BUF ; R2 <- &BUF
STRB R1, [R2] ; BUF[0] <- (low byte of R1)
STOP B STOP ; Stay here forever
ENDWhat each directive does:
AREA <name>, CODE|DATA, READONLY|READWRITE: defines a section. Put the vector table and program text inCODE, READONLY; put variables inDATA, READWRITE.EXPORT <symbol>: makes a label visible to the linker/other modules.DCD, DCW, DCB <values>: allocate and initialize words, halfwords, or bytes.SPACE <n>: reserve n bytes of uninitialized storage in RAM.ALIGN: align to a suitable boundary (commonly 4 bytes for words).ENTRY: mark the entry point of the image for the toolchain.END: end of source file.
Notes:
- The first two words in
__Vectorsmust be the initial stack pointer value and the address ofReset_Handler. - The assembler/linker places sections in appropriate memory regions based on the target device and linker script.
- Labels must start at the beginning of the line (no indentation), while instructions and directives should be indented for proper assembly.
- Variables in
READWRITEareas are initialized to zero by default.