Instructions

3 address instruction format
- OP: operation
- Rd: destination register
- Rn, Rm: operands

Summary

Data Processing

Syntax

Format: <op>{cond}{S} Rd, Rn, Op2

List

Operation Notes
ADD
ADC Add with carry (for 64 bit arithmetic)
SUB
SBC Subtract with carry
RSB Reverse subtract (i.e Op2 - Op1)
DIVS/DIVU Divide signed/unsigned
MUL

List

Operation Notes
AND Bitwise AND
ORR
EOR Bitwise XOR
BIC Bitwise clear: Rn * Op2' (bitwise complement of Op2)
ORN Or-not: Rn + Op2'

List

Operation Meaning Notes
LSL Logical shift left
LSR Logical shift right
ASR Arithmetic shift right Copies leftmost bit
ROR Rotate right

List

Operation Syntax Notes
MOV MOV{S}{cond} Rd, Op2
MOV MOV{cond} Rd, #imm16 16 bit immediate data, `Rd <- 0x0000
MOVT MOVT{cond} Rd, #imm16 Stands for move top, Rd[31 % 16] <- imm16
MVN MVN{S}{cond} Rd, Op2 Rd <- Op2

Memory Access

Syntax

Format: <op>{size}{cond} Rd, <address>

  • op: operation mnemonic
  • size?: size to load/store, defaults to word (4 bytes)
    • B byte
    • H half word (2B)
    • SB signed byte
    • SH signed halfword
  • cond?: ARM V7 Assembly#Conditions
  • Rd: dest. register
  • address: see below
Table

Operation Full Name Description
LDR Load register Rd <- mem[<address>]
STR Store register Rd -> mem[<address>]

PC Relative Load

Syntax

Format: ADR{cond} Rd, label

  • label: label of some line of code

Putting Address in Register

Syntax

Format: LDR{size}{cond} Rd, label

  • label: name for a line of code

Branch

Syntax

Format: B{cond} label

  • label: label of some line of code

Data Processing Instructions

Example

ADD R2, R0, #1

where #1 is an immediate value (i.e constant)

reg[2] <- reg[0] + 1

Syntax

Format: <op>{cond}{S} Rd, Rn, Op2

Example

If we try -1 + -1:

with a carry bit , the PSR flags will be set to:

  • C: true
  • Z: false
  • V: false
  • N: true
Examples

ADDS R2, R0, #1

the S flag is used to "set" PSR flags

reg[2] <- reg[0] + 1, PSR <- N, Z, V, C


ADDEQ R5, R3, R4

if (Z == 1) reg[5] <- reg[3] + reg[4]

Arithmetic Operations

Run on the ALU

List

Operation Notes
ADD
ADC Add with carry (for 64 bit arithmetic)
SUB
SBC Subtract with carry
RSB Reverse subtract (i.e Op2 - Op1)
DIVS/DIVU Divide signed/unsigned
MUL

Logical Operators

List

Operation Notes
AND Bitwise AND
ORR
EOR Bitwise XOR
BIC Bitwise clear: Rn * Op2' (bitwise complement of Op2)
ORN Or-not: Rn + Op2'

Note

There is no NOT operator. Instead, use EOR against -1.

Example

Program in C:

i--;
if (i < 0) {
    i += 10;
}

Equivalent in ARM ASM:

SUB R1, R1, #1
ADDLT R1, R1, #10

where i is R1.

Equivalent shorthand:

SUB R1, #1
ADDLT R1, #10

Flexible Operands

Info

Flexible operands can either be:

  • A constant (an 8-bit value) shifted 0-31 bits, which is immediate data encoded in the machine instruction
    • e.g ADD R2, R0, #1
  • A register value shifted 0-31 bits
Syntax

Format: <op>{S}{cond} Rd, Rn, <Rs | #n>

  • Rs | #n # of bit positions to shift
List

Operation Meaning Notes
LSL Logical shift left
LSR Logical shift right
ASR Arithmetic shift right Copies leftmost bit
ROR Rotate right

Figure

Example

ADD R2, R0, R1, LSL #2

Same as

reg[2] <- reg[0] + (reg[1] << 2)

Data Movement

List

Operation Syntax Notes
MOV MOV{S}{cond} Rd, Op2
MOV MOV{cond} Rd, #imm16 16 bit immediate data, `Rd <- 0x0000
MOVT MOVT{cond} Rd, #imm16 Stands for move top, Rd[31 % 16] <- imm16
MVN MVN{S}{cond} Rd, Op2 Rd <- Op2

Example

Move 0x1234ABCD into R2

MOV R2, #0xABCD ; now R2 is `0000ABCD`
MOVT R2, #0x1234 ; now R2 is `1234ABCD

Memory Access Instructions

Access [[Memory]] on [[The Stack]]

Syntax

Format: <op>{size}{cond} Rd, <address>

  • op: operation mnemonic
  • size?: size to load/store, defaults to word (4 bytes)
    • B byte
    • H half word (2B)
    • SB signed byte
    • SH signed halfword
  • cond?: [[ARM V7 Assembly#Conditions]]
  • Rd: dest. register
  • address: see below
Table

Operation Full Name Description
LDR Load register Rd <- mem[<address>]
STR Store register Rd -> mem[<address>]

Syntax - Address

Treats register value like a pointer

  1. With immediate offset
  2. With register offset
    • <address> = [Rn, ± Rm {, shift}]
Example - Immediate Offset

`R0: [0000 0100]`
LDR R1, [R0]

reg[1] <- mem[reg[0]]
R1: [1234 ABCD]


LDR R2, [R0, #4]

reg[2] <- mem[reg[0] + 4]
R2: [AAAA 5555]


LDRSB R3, [R0]

Load signed byte

R3: [FFFF FFCD]

Example - Register Offset

LDR R1, [R0, -R2]

reg[1] <- mem[reg[0] - reg[2]]


LDR R1, [R0, R2, LSL #2]

reg[1] <- mem[reg[0] + (reg[2] << 2)]

Pre and Post-Indexed Addressing

Info

Indexed addressing allows us to auto-increment the value of a register by some offset before or after using it. Think of it like ++i vs i++.

Syntax

  • Normal: <address> = [Rn, #offset]
  • Pre-indexed: <address> = [Rn, #offset]!
  • Post-indexed: <address> = [Rn], #offset

Example

LDR R3, [R1, #4]!

reg[3] <- mem[reg[1] + 4]; reg[1] <- reg[1] + 4


LDR R3, [R1], #4

reg[3] <- mem[reg[1]]; reg[1] <- reg[1] + 4

PC-Relative Load

See program counter, PC-relative addressing

Syntax

Format: LDR{size}{cond} Rd, label

  • label: name for a line of code
Example

LDR R1, SUM

reg[1] <- mem[&SUM]

where SUM is some label to some line in the code

We can write the pseudo-instruction:

LDR R1, =SUM

to store the address of the label SUM rather than the value stored at SUM, which would make it almost equivalent to the ADR instruction.

Putting Address in a Register

See program counter, PC-relative addressing

Syntax

Format: ADR{cond} Rd, label

  • label: label of some line of code
Example

ADR, R2, SUM

reg[2] <- &SUM

Load and Store Multiple

This requires knowledge of [[The Stack]]. More details will be available there.

Syntax

Format: <op>{cond}{address-mode} Rn{!}, reg-list{^}

  • op: operation mnemonic
  • cond?: [[ARM V7 Assembly#Conditions]]
  • address-mode: [[The Stack#Full vs Empty, Ascending vs Descending Stack]]
    • FD full descending
    • FA full ascending
    • ED empty descending
    • EA empty ascending
  • Rn base register for the load operation (e.g stack pointer for loading)
  • ! specifies base register write back (i.e base register gets updated after the transfer, by one word for each register in the register list)
  • reg-list comma separated list of register names and ranges enclosed in braces
Table

Operation Full Name Alias
LDM Load multiple PUSH
STM Store multiple POP

Table

Stack Type Push Pop
Full descending STMFD (STMDB) LDMFD (LDMIA)
Full ascending STMFA (STMIB) LDMFA (LDMDA)
Empty descending STMED (STMDA) LDMED (LDMIB)
Empty ascending STMEA (STMIA) LDMEA (LDMDB)

Example

STMFD r13!, {r0-r5, LR} ; Push r0-r5 and link register onto stack
LDMFD r13!, {r0-r5, PC} ; Pop r0-r5 and the link register into the program counter from stack

Branch Instructions

See branch instruction

Syntax

Format: B{cond} label

  • label: label of some line of code

Compare Instructions

Info

Compares two operands and updates the PSR flags (N, Z, C, V). Operands remain unchanged.

Syntax

Format: <op>{cond} Rn, Op2

Table

Operation Name Description
CMP Compare reg[n] - op2
CMN Compare negative reg[n] + op2
TST Test
TEQ Test equal

TST checks if any set bits in op2 are also set in reg[n], e.g reg[n] = 1111 1111 and op2 = 0101 1010 would be true. TEQ checks for an exact match.

Compare and Branch

Syntax

Format: <op> Rn, label

Table

Operation Meaning
CBZ Branch to label if reg[n] == 0
CBNZ Branch to label if reg[n] != 0

Example

if (x == 0) {
    y++
} else {
    y--;
}

With CMP:

CMP R0, #0
ADDEQ R1, #1
SUBNE R1, #1

With CBZ/CBNZ:

     CBZ R0, ELSE
     ADD R1, #2
ELSE SUB R1, #1