General Reference

Size of bytes

  1. 1 byte = 8 bits

  2. 1KB = 2102^{10} bytes = 1024 bytes

  3. 1MB = 2202^{20} bytes = 1,048,576 bytes

  4. 1GB = 2302^{30} bytes = 1,073,741,824 bytes

Memory sizes

Size of numbers

Type Bytes Bits Range
signed char 1 8 −128→+127-128 \to +127
unsigned char 1 8 0→+2550 \to +255
short int 2 16 −32,768→+32,767(±32KB)-32,768 \to +32,767 \quad (\pm 32\text{KB})
unsigned short int 2 16 0→+65,535(64KB)0 \to +65,535 \quad\qquad (64\text{KB})
unsigned int 4 32 0→+4,294,967,295(4GB)0 \to +4,294,967,295 \quad (4\text{GB})
int 4 32 −2,147,483,648→+2,147,483,647(±2GB)-2,147,483,648 \to +2,147,483,647 \ (\pm 2\text{GB})
long int 4 32 −2,147,483,648→+2,147,483,647(±2GB)-2,147,483,648 \to +2,147,483,647 \ (\pm 2\text{GB})
long long int 8 64 −(263)→(263)−1-(2^{63}) \to (2^{63})-1
float 4 32 ±1.2×10−38→±3.4×1038(∼7 decimals)\pm1.2\times 10^{-38} \to \pm 3.4\times 10^{38} \ (\sim7 \text{ decimals})
double 8 64 ±2.3×10−308→±1.7×10308(∼15−17 decimals)\pm2.3 \times 10^{-308} \to \pm1.7\times 10^{308} \ (\sim 15-17 \text{ decimals})
long double 12 96 ±3.4×10−4932→±1.1×104932(∼18−19 decimals)\pm3.4\times 10^{-4932} \to \pm1.1\times 10^{4932} \ (\sim 18-19 \text{ decimals})

Data types should be aligned to address that is a multiple of the data bus.

Little Endian (LSB at lowest address; assume this) vs Big Endian (MSB at highest address).

Size of instructions and its components/operands

  1. One instruction: 32 bits / 4 bytes

  2. Condition flags: 4 bits (Bits 28-31)

  3. Opcode: 8 bits (Bits 20-27)

  4. Register: 4 bits (Since there are 16 possible registers in the processor)

  5. Immediate value: 12 bits (4 rotate right bits + 8 bit immediate value.)

Execution Cycle

Fetch-Decode-Execute ⟹\implies PC value is 8 bytes ahead of current instruction being executed. For PC-related addressing, must have offset of 8bytes. The max offset is ±4096\pm 4096 bytes or (#0xFC) , ∵\because offset field only has 12 bits.

Instruction Set

VisUAL ARM Instruction Set
Summary Opcode Syntax
Move MOV MOV{S}{cond} dest, op1 {, SHIFT op #expression}
S=1: NZC, C if shift occurs.
Move Negated MVN MVN{S}{cond} dest, op1 {, SHIFT op #expression}
Inverts op1 bitwise (1’s comp) before moving.
S=1: NZC, C if shift occurs.
LDR Psuedo-Instruction LDR LDR{S}{cond} dest, =expression
Add ADD ADD{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1, updates NZCV.
Add with Carry ADC ADC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
dest = op1 + op2 + C
S=1, updates NZCV.
Subtract SUB SUB{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1, updates NZCV.
Subtract with Carry SBC SBC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
dest = op1 - op2 - NOT(C)
S=1, updates NZCV.
Reverse Subtract RSB RSB{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
dest = op1 - op2
S=1, updates NZCV.
Reverse Subtract with Carry RSC RSC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
dest = op2 - op1 - NOT(C)
S=1, updates NZCV.
Bitwise And AND AND{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1: NZC, C if shift occurs.
Bitwise Exclusive Or EOR EOR{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1: NZC, C if shift occurs.
Bitwise Clear BIC BIC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1: NZC, C if shift occurs.
Bitwise Or ORR ORR{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
S=1: NZC, C if shift occurs.
Logical Shift Left LSL LSL{S}{cond} dest, op1, op2
S=1: NZC, C gets the last bit shifted out.
Logical Shift Right LSR LSR{S}{cond} dest, op1, op2
S=1: NZC, C gets the last bit shifted out.
Arithmetic Shift Right ASR ASR{S}{cond} dest, op1, op2
MSB unchanged. If S=1, C=LSB.
S=1: NZC, C gets the last bit shifted out.
Rotate Right ROR ROR{S}{cond} dest, op1, op2
LSB into MSB. If S=1, C=LSB.
S=1: NZC, C gets the last bit shifted out.
Rotate Right and Extend RRX RRX{S}{cond} op1, op2
C into MSB. If S=1, C=LSB.
S=1: NZC, C gets the last bit shifted out.
Compare CMP CMP{cond} op1, op2 {, SHIFT_op #expression}
Test (op1 - op2), same as SUBS without modification
Always updates NZCV.
Compare Negated CMN CMN{cond} op1, op2 {, SHIFT_op #expression}
Tests (op1 + op2), same as ADDS w/o modification
Always updates NZCV.
Test Bit(s) Set TST TST{cond} op1, op2 {, SHIFT_op #expression}
Bitwise AND b/w operands
Always updates NZC.
Test Equals TEQ TEQ{cond} op1, op2 {, SHIFT_op #expression}
Bitwise XOR b/w operands
Always updates NZC.
Load Register LDR LDR{B}{cond} dest, [source {, OFFSET}] Offset addressing
LDR{B}{cond} dest, [source, OFFSET]! Pre-indexed addressing
LDR{B}{cond} dest, [source], OFFSET Post-indexed addressing
Store Register STR STR{B}{cond} source, [dest {, OFFSET}] Offset addressing
STR{B}{cond} source, [dest, OFFSET]! Pre-indexed addressing
STR{B}{cond} source, [dest], OFFSET Post-indexed addressing
Load Multiple Registers LDM[dir] LDM[dir]{cond} source, {list of registers}
Store Multiple Registers STM[dir] STM[dir]{cond} dest, {list of registers}
Branch B B{cond} target
Branch with Link BL BL{cond} target
Stop Emulation END END{cond}

Memory Access and Clock Cycles per Instruction

ARM Memory Accesses vs. Clock Cycles (N = Register List Size)
Instruction Type Memory Accesses (Data + Instr) Total Accesses Clock Cycles
Data Processing (Standard)
MOV, ADD, SUB, AND, ORR, etc. 1 (Instr) + 0 (Data) 1 1
MOVEQ (Conditional Move) 1 (Instr) + 0 (Data) 1 1 (True or False)
Comparisons (CMP, CMN, TST, TEQ) 1 (Instr) + 0 (Data) 1 1
Data Proc. with Register Shift (e.g. LSL Rs) 1 (Instr) + 0 (Data) 1 1
Control Flow (Branches modify PC)
B (Unconditional Branch) 1 (Instr) + 0 (Data) 1 3 (Pipeline Flush)
BEQ / BCC (Conditional Branch) 1 (Instr) + 0 (Data) 1 1 (False) or 3 (True)
BL (Branch with Link) 1 (Instr) + 0 (Data) 1 3 (Pipeline Flush)
BX LR (Branch and Exchange) 1 (Instr) + 0 (Data) 1 3 (Pipeline Flush)
MOV PC, LR (Return from Branch) 1 (Instr) + 0 (Data) 1 3 (Pipeline Flush)
Data Proc. writing to PC (e.g. ADD PC, ...) 1 (Instr) + 0 (Data) 1 3 (Pipeline Flush)
Single Data Transfer
LDR / STR (Single Load/Store) 1 (Instr) + 1 (Data) 2 2
LDREQ / STREQ (Conditional) 1 (Instr) + 0 or 1 (Data) 1 or 2 1 (False) or 2 (True)
Block Data Transfer (Stack)
LDMFD (Load Multiple, Full Desc.) 1 (Instr) + N (Data) N+1N+1 N+2N+2
STMFD (Store Multiple, Full Desc.) 1 (Instr) + N (Data) N+1N+1 N+2N+2

Condition Codes

ARM Bcc Conditions
Code Suffix Flags Meaning
0000 EQ Z=1Z = 1 Equal
0001 NE Z=0Z = 0 Not equal
0010 CS or HS C=1C = 1 Higher or same, unsigned
0011 CC or LO C=0C = 0 Lower, unsigned
0100 MI N=1N = 1 Negative
0101 PL N=0N = 0 Positive or zero
0110 VS V=1V = 1 Overflow
0111 VC V=0V = 0 No overflow
1000 HI C=1C = 1 and Z=0Z = 0 Higher, unsigned
1001 LS C=0C = 0 or Z=1Z = 1 Lower or same, unsigned
1010 GE N=VN = V Greater than or equal, signed
1011 LT N≠VN \neq V Less than, signed
1100 GT Z=0Z = 0 and N=VN = V Greater than, signed
1101 LE Z=1Z = 1 and N≠VN \neq V Less than or equal, signed
1110 AL Can have any value Always. This is the default when no suffix is specified.
1111 NV Reserved (unused)

SUBS sets C=1 when no borrow (A - B, where A >=>= B); clears C=0 if borrow (A - B, where A << B).

Condition to set the flags:

Instruction Anatomy

Data processing instructions

Data Processing with Immediate Value
XXXCCS Rd, Rs1, #immediate (rotated)
Data Processing with Immediate Shift
XXXCCS Rd, Rs1, Rs2, {shft #}
Data Processing with Register Shift
XXXCCS Rd, Rs1, Rs2, {shft Rshift}

Branch instructions

Branch Instruction Format; B(L)CC Offset

If L=0, then is B. If L=1, then is BL. Offset is distance between current instruct & target addr. Effectively acts as 26-bit offset. Branch range: ±32\pm 32 Mbytes.

Load/store instructions

Load/Store Single Word/Byte (Register Offset)
LDR/STR{B}CC Rs, [Rd, offset pre or post]!
Load/Store Single Word/Byte (Immediate Offset)
LDR/STR{B}CC Rs, [Rd, offset pre or post]!

(The maximum offset for register indirect with immediate value is ±4096=±212\pm 4096= \pm 2^{12} bytes. The sign is determined by U bit.)
(1/0): P = Pre/post; U = add/subtract; B = byte/32-bit word; W = writeback/no wb; L = load/store;

Load/Store Multiple Instructions
LDM/STM{mode}CC Rs{!}, {register list}

B becomes "don’t care" bit; register list bit 0 is R0, bit 15 is R15, 1=include that register.

Summary of Key Instruction Identifiers (Bits 27-25)
Bits 27–25 Instruction Category Meaning
000 Data Processing Register/Shift Operand (I=0I=0)
001 Data Processing Immediate Operand (I=1I=1)
010 Load/Store Single Register Offset
011 Load/Store Single Immediate Offset
100 Load/Store Multiple Block Data Transfer (LDM/STM)
101 Branch Branch/Jump Instruction (B/BL)
Instruction Type (Opcode) Field (Bits 24-21)
Code Instruction Code Instruction
0000 AND 1000 TST
0001 EOR 1001 TEQ
0010 SUB 1010 CMP
0011 RSB 1011 CMN
0100 ADD 1100 ORR
0101 ADC 1101 MOV
0110 SBC 1110 BIC
0111 RSC 1111 MVN
Shift Type Encoding (Bits 6 and 5)
Code Shift type
00 LSL
01 LSR
10 ASR
11 ROR/RRX
PU^WL Bits Instruction
00011 LDMFA (Pop)
01011 LDMFD (Pop)
10010 STMFD (Push)
11010 STMFA (Push)
00010 STMED (Push)
01010 STMEA (Push)
10011 LDMEA (Pop)
11011 LDMED (Pop)

Flow control

IF statement: reverse the condition to reduce jump instructions.
Condtional execution: add the condtion codes to the instruction (e.g. MOVEQ). If using multiple of these, ensure the CSPR unchanged.

Compound AND: If first condition fail, branch out immediately.
Compound OR: If first cond pass, branch immediately.

SWITCH with narrow consecutive values, use jump table.
SWTICH with wide range of values, use forked cascade.

PRE-test loops (WHILE): Test condition at the start, branch out if fail.
POST-test loops (DO-WHILE): Test at the end.

FOR loops are pre-test loops.

ASCII table

Bits: b7b6b5→b_7b_6b_5 \rightarrow / b4b3b2b1↓b_4b_3b_2b_1 \downarrow 000 001 010 011 100 101 110 111
0 1 2 3 4 5 6 7
0 0 0 0 0 NUL DLE SP 0 @ P ` p
0 0 0 1 1 SOH DC1 ! 1 A Q a q
0 0 1 0 2 STX DC2 " 2 B R b r
0 0 1 1 3 ETX DC3 # 3 C S c s
0 1 0 0 4 EOT DC4 $ 4 D T d t
0 1 0 1 5 ENQ NAK % 5 E U e u
0 1 1 0 6 ACK SYN & 6 F V f v
0 1 1 1 7 BEL ETB ’ 7 G W g w
1 0 0 0 8 BS CAN ( 8 H X h x
1 0 0 1 9 HT EM ) 9 I Y i y
1 0 1 0 10 LF SUB * : J Z j z
1 0 1 1 11 VT ESC + ; K [ k {
1 1 0 0 12 FF FS , < L \ l |
1 1 0 1 13 CR GS - = M ] m }
1 1 1 0 14 SO RS . > N ^ n ~
1 1 1 1 15 SI US / ? O _ o DEL

Stacks

Type Characteristics Push Action (Store) Pop Action (Load) Access Top Item
FD Full Descending
Grows Down (↓\downarrow)
SP points to: Data
Pre-Decrement
STR Rn, [SP, #-4]!
PU^WL: 1010
Post-Increment
LDR Rn, [SP], #4
PU^WL: 0111
No Offset
LDR Rn, [SP]
ED Empty Descending
Grows Down (↓\downarrow)
SP points to: Empty
Post-Decrement
STR Rn, [SP], #-4
PU^WL: 0010
Pre-Increment
LDR Rn, [SP, #4]!
PU^WL: 1111
Plus 4
LDR Rn, [SP, #4]
FA Full Ascending
Grows Up (↑\uparrow)
SP points to: Data
Pre-Increment
STR Rn, [SP, #4]!
PU^WL: 1110
Post-Decrement
LDR Rn, [SP], #-4
PU^WL: 0011
No Offset
LDR Rn, [SP]
EA Empty Ascending
Grows Up (↑\uparrow)
SP points to: Empty
Post-Increment
STR Rn, [SP], #4
PU^WL: 0110
Pre-Decrement
LDR Rn, [SP, #-4]!
PU^WL: 1011
Minus 4
LDR Rn, [SP, #-4]

Modular Programming

Branch to subroutine (both change LR and PC).

  1. BL.

  2. MOV LR PC; B SUBROUTINE.

Return to calling program (both only change PC).

  1. BX LR.

  2. MOV PC LR.

STMFD SP! {R6-R7, LR}: R6 at lowest memory, LR at highest memory, i.e. SP pointing at R6.
LDMFD SP! {R6-R7, PC}: PC takes over saved LR content.
Immediately after executing BL Sub1 located at 0x300, LR = 0x304.
Registers:

When pushing LR or extra registers at the start of a nested subroutine, the SP shifts. To recalculate LDR offsets:
Formula: New Offset = Old Offset + (Number of Extra Registers Pushed × 4 bytes)
Example: If a parameter was at [SP, #24] and you add LR to your push list (STMFD SP!, R4-R7, LR), you pushed 1 extra register. New offset = 24 + (1 × 4) = 28.

LDR R1, [R0], #4
MOV R2, R0
STMFD SP!, {R1, R2}
BL Sub1

Assuming R0=0x100, V1 stored at 0x100, V2 stored at 0x104.
R1 passed in by value, R2 passed in by reference.

Each recursive call saves the address of the next instruction using LR. To find number of recursive calls, find the number of repeated addresses saved, that are close to address in PC.