Instructions
arm64AArch64 Common Instructions
Core ARM64 instructions — MOV, LDR/STR, B/BL/BLR, CMP, ADD/SUB, and RET — with their encodings and reverse-engineering patterns.
ARM64 instructions are all 32 bits wide (fixed-length), which makes disassembly trivial compared to x86-64. Instructions follow a destination-first, source-second convention in ARM syntax.
MOV
MOV X0, X1 ; X0 = X1 (alias for ORR X0, XZR, X1)
MOV X0, #42 ; X0 = 42 (alias for MOVZ X0, #42)
MOVZ X1, #0x1234 ; X1 = 0x1234 (zero other halfwords)
MOVK X1, #0x5678, LSL #16 ; keep other bits, set bits 31:16MOV is a pseudoinstruction; the assembler chooses ORR, MOVZ, or MOVN
as appropriate.
LDR / STR (Load and Store)
LDR X0, [X1] ; X0 = *(uint64_t*)X1
LDR W0, [X1] ; W0 = *(uint32_t*)X1 (zero-extends to X0)
LDRB W0, [X1] ; W0 = *(uint8_t*)X1
LDRH W0, [X1] ; W0 = *(uint16_t*)X1
LDRSB X0, [X1] ; sign-extend byte → X0
LDRSH X0, [X1] ; sign-extend halfword → X0
STR X0, [X1] ; *(uint64_t*)X1 = X0
STR W0, [X1, #8] ; *(uint32_t*)(X1+8) = W0
; Pre-index (update X1 before access)
LDR X0, [X1, #8]! ; X1 += 8; X0 = *X1
; Post-index (update X1 after access)
LDR X0, [X1], #8 ; X0 = *X1; X1 += 8
; Pair
STP X29, X30, [SP, #-16]! ; push FP and LR (function prologue)
LDP X29, X30, [SP], #16 ; pop FP and LR (function epilogue)B / BL / BLR / BR (Branches)
| Instruction | Operation |
|---|---|
B label | Unconditional branch (PC-relative ±128 MB) |
BL label | Branch with Link: LR = PC+4; goto label (call) |
BLR Xn | Branch with Link to Register (indirect call) |
BR Xn | Branch to Register (indirect jump / tail call) |
B.cond label | Conditional branch (e.g. B.EQ, B.NE, B.LT) |
CBZ Xn, label | Branch if Xn == 0 (compare-and-branch, no flags) |
CBNZ Xn, label | Branch if Xn != 0 |
TBZ Xn, #bit, label | Branch if bit N of Xn == 0 |
CMP / TST
CMP X0, X1 ; flags ← X0 - X1 (alias: SUBS XZR, X0, X1)
CMP X0, #100
TST X0, #0xFF ; flags ← X0 & 0xFF (alias: ANDS XZR, X0, #0xFF)ADD / SUB
ADD X0, X1, X2 ; X0 = X1 + X2
ADD X0, X1, #16 ; X0 = X1 + 16
SUB SP, SP, #32 ; allocate 32 bytes on stack
ADDS X0, X1, X2 ; ADD and set flags (S suffix → update PSTATE)
SUBS X0, X1, X2 ; SUB and set flagsRET
RET ; branch to X30 (LR) — return to caller
RET X17 ; branch to X17 (used in veneers/PLT stubs)RET is not a pop — it is BR LR. The return address must have been loaded
into LR by a previous BL/BLR, or restored from the stack.
Reverse-engineering notes
- The prologue
STP X29, X30, [SP, #-16]!saves the frame pointer and link register; the matching epilogue isLDP X29, X30, [SP], #16; RET. BLR X16orBLR X17in a PLT stub jumps through the GOT to a lazy-linked library function.CBZ/CBNZare compact null-pointer and boolean checks that produce no separateCMPinstruction — decompilers render them asif (!x)/if (x).- Fixed-length encoding means you can reliably disassemble backwards: subtract 4 to get the previous instruction, unlike x86-64.