Skip to content

Flow Control and Addressing Modes ​

In this experiment, you will learn how to implement looping, branching, and decision-making in ARM Assembly. Additionally, you will explore various addressing modes that ARM offers for flexible and efficient memory access.

Branching ​

Branching changes the program's execution flow by jumping to another location in memory.

  • Unconditional branch: B label
  • Conditional branch: Executes only if a specific condition flag is set.
  • Branch with Link (BL): Calls a subroutine.
  • Branch and Exchange (BX): Returns from subroutine.

Conditional Execution ​

ARM supports conditional execution for most instructions by adding a condition suffix.

Condition Codes ​

SuffixMeaningFlags checked
EQEqualZ = 1
NENot EqualZ = 0
CS/HSCarry Set / Unsigned ≥C = 1
CC/LOCarry Clear / Unsigned <C = 0
MIMinus / NegativeN = 1
PLPlus / Positive/ZeroN = 0
VSOverflow SetV = 1
VCOverflow ClearV = 0
HIUnsigned >C = 1 & Z = 0
LSUnsigned ≤C = 0 or Z = 1
GESigned ≥N = V
LTSigned <N ≠ V
GTSigned >Z = 0 & N = V
LESigned ≤Z = 1 or N ≠ V
ALAlways (default)—

Load/Store Instructions ​

Load and Store Instructions have the following format:

asm
[LABEL] LDR{cond}{mod} Rt, [Rn{, #offset}]
[LABEL] STR{cond}{mod} Rt, [Rn{, #offset}]

Where:

  • <mod> can be one of the following:
    • B - Byte (8 bits)
    • H - Halfword (16 bits)
    • SB - Signed Byte (8 bits)
    • SH - Signed Halfword (16 bits)
    • D - Doubleword (64 bits)
  • offset can be a register, immediate value, or a barrel shifted value.
  • cond is an optional condition code.

Addressing Modes ​

Common ways to access memory in ARM:

ModeExampleDescription
ImmediateMOV R0, #15Constant operand
RegisterMOV R0, R1Operand in register
DirectLDR R0, VALUEValue from memory label
IndirectLDR R0, [R1]Value from address in register
Pre-Indexed Without UpdateLDR R0, [R1, #4]Add offset before load (no update)
Pre-indexedLDR R0, [R1, #4]!Add offset before load (update pointer)
Post-indexedLDR R0, [R1], #4Add offset after load
Register IndexedLDR R0, [R1, R2]Base + register index

Examples ​

Example 1: Looping Through an Array and a String ​

This program:

  1. Loops through an integer array using a length counter (pre-known size).
  2. Loops through a string until a null terminator is reached.
asm

    AREA RESET, CODE, READONLY
    EXPORT __Vectors
__Vectors
    DCD 0x20001000
    DCD Reset_Handler
    ALIGN
    AREA M_DATA, DATA, READONLY
N      DCD 5
ARRAY  DCD 3, -7, 2, -2, 10
PTR_A  DCD ARRAY

string1 DCB "Hello, ARM!", 0
PTR_S   DCD string1

    AREA MYCODE, CODE, READONLY
    ENTRY
    EXPORT Reset_Handler
Reset_Handler

; ---- Array loop using length counter ----
    LDR R1, N        ; Number of elements
    LDR R2, PTR_A    ; Pointer to array
    MOV R0, #0       ; Sum accumulator

arrayLoop
    LDR R3, [R2], #4 ; Load next element, post-increment pointer
    ADD R0, R0, R3
    SUBS R1, R1, #1
    BGT arrayLoop

; ---- String loop using null terminator ----
    LDR R4, PTR_S    ; Pointer to string
    MOV R5, #0       ; Character counter

stringLoop
    LDRB R6, [R4], #1 ; Load next char
    CBZ R6, stringDone
    ADD R5, R5, #1
    B stringLoop

stringDone
STOP B STOP
    END

Example 2 - Case Conversion of a Null-Terminated String ​

This program converts a null-terminated string to uppercase.

asm
 AREA RESET, CODE, READONLY
    EXPORT __Vectors
__Vectors
    DCD 0x20001000          
    DCD Reset_Handler
    ALIGN
string  DCB "Arm Assembly!", 0


    AREA M_DATA, DATA, READWRITE
conv_str SPACE 13           ; Buffer for converted string (same length as input)

    AREA MYCODE, CODE, READONLY
    ENTRY
    EXPORT Reset_Handler
Reset_Handler

    LDR R0, =string         ; Pointer to input string
    LDR R1, =conv_str       ; Pointer to output buffer

caseConvLoop
    LDRB R2, [R0], #1       ; Load byte from input and post-increment R0
    CBZ R2, done            ; If zero (end of string), jump to done

    CMP R2, #'a'            ; Compare char to 'a'
    BLT storeChar           ; If less, skip conversion, just store

    CMP R2, #'z'            ; Compare char to 'z'
    BGT storeChar           ; If greater, skip conversion, just store

    BIC R2, R2, #32         ; Convert to uppercase by clearing bit 5

storeChar
    STRB R2, [R1], #1       ; Store char to output buffer and post-increment
    B caseConvLoop          ; Loop back

done
    MOV R2, #0
    STRB R2, [R1]           ; Null-terminate the output string

STOP
    B STOP                  ; Infinite loop

    END

Tasks ​

Task 1 - Sum All Even Numbers in an Array ​

  • Write an ARM assembly program to sum all even integers from an array.

Task 2 - Count the Number of Vowels in a String ​

  • Write an ARM assembly program to count the number of vowels (a, e, i, o, u) in a null-terminated string.