Instructions
3 address instruction format
- OP: operation
- Rd: destination register
- Rn, Rm: operands
Summary
Data Processing
Memory Access
PC Relative Load
Putting Address in Register
Branch
Data Processing Instructions
Format: <op>{cond}{S} Rd, Rn, Op2
op
: operation mnemoniccond?
: ARM V7 Assembly#ConditionsS?
: should set flags in PSRRd
: dest. registerRn
: Operand 1 (reg.)Op2
: Operand 2 (reg. or immediate data)
If we try -1 + -1:
with a carry bit
C
:true
Z
:false
V
:false
N
:true
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
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
Operation | Notes |
---|---|
AND | Bitwise AND |
ORR | |
EOR | Bitwise XOR |
BIC | Bitwise clear: Rn * Op2' (bitwise complement of Op2 ) |
ORN | Or-not: Rn + Op2' |
There is no NOT operator. Instead, use EOR against -1.
Flexible Operands
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
- e.g
- A register value shifted 0-31 bits
Operation | Meaning | Notes |
---|---|---|
LSL | Logical shift left | |
LSR | Logical shift right | |
ASR | Arithmetic shift right | Copies leftmost bit |
ROR | Rotate right |
Data Movement
Memory Access Instructions
Access [[Memory]] on [[The Stack]]
Format: <op>{size}{cond} Rd, <address>
op
: operation mnemonicsize?
: size to load/store, defaults to word (4 bytes)B
byteH
half word (2B)SB
signed byteSH
signed halfword
cond?
: [[ARM V7 Assembly#Conditions]]Rd
: dest. registeraddress
: see below
Operation | Full Name | Description |
---|---|---|
LDR | Load register | Rd <- mem[<address>] |
STR | Store register | Rd -> mem[<address>] |
`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]
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
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++
.
PC-Relative Load
See program counter, PC-relative addressing
Format: LDR{size}{cond} Rd, label
label
: name for a line of code
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
Format: ADR{cond} Rd, label
label
: label of some line of code
ADR, R2, SUM
reg[2] <- &SUM
Load and Store Multiple
This requires knowledge of [[The Stack]]. More details will be available there.
Format: <op>{cond}{address-mode} Rn{!}, reg-list{^}
op
: operation mnemoniccond?
: [[ARM V7 Assembly#Conditions]]address-mode
: [[The Stack#Full vs Empty, Ascending vs Descending Stack]]FD
full descendingFA
full ascendingED
empty descendingEA
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
Operation | Full Name | Alias |
---|---|---|
LDM |
Load multiple | PUSH |
STM |
Store multiple | POP |
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
Format: B{cond} label
label
: label of some line of code
Compare Instructions
Compares two operands and updates the PSR flags (N, Z, C, V). Operands remain unchanged.
Format: <op>{cond} Rn, Op2
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
Format: <op> Rn, label
Operation | Meaning |
---|---|
CBZ |
Branch to label if reg[n] == 0 |
CBNZ |
Branch to label if reg[n] != 0 |
- Can only branch forwards
- Does not affect PSR flags