ARM Assembly Cheat Sheet
AArch64 register conventions, common instructions, addressing modes, and a full function-call example for systems programming.
3 PagesAdvancedFeb 5, 2026
AArch64 Registers
The general-purpose and special register set (64-bit names, x0-x30).
- x0-x7- argument/result registers for function calls (AAPCS64)
- x8- indirect result register / Linux syscall number
- x9-x15- caller-saved temporary registers
- x16-x17 (IP0/IP1)- intra-procedure-call temp registers, used by linkers
- x18- platform register, reserved on some OSes (don't use)
- x19-x28- callee-saved registers, must be preserved across calls
- x29 (FP)- frame pointer
- x30 (LR)- link register, holds return address after bl
- sp- stack pointer, must stay 16-byte aligned
- wN- 32-bit view of register xN (w0 is low 32 bits of x0)
Data Processing
Arithmetic, logical, and move instructions.
asm
mov x0, #5 // x0 = 5mov x1, x0 // x1 = x0add x2, x0, x1 // x2 = x0 + x1sub x3, x2, #1 // x3 = x2 - 1mul x4, x2, x3 // x4 = x2 * x3udiv x5, x4, x2 // x5 = x4 / x2 (unsigned)and x6, x0, #0xF // bitwise ANDorr x7, x0, x1 // bitwise OReor x8, x0, x1 // bitwise XORlsl x9, x0, #2 // logical shift left by 2 (x0 * 4)lsr x10, x0, #1 // logical shift right by 1cmp x0, x1 // compare (sets NZCV flags)
Load/Store & Addressing
Moving data between registers and memory.
asm
ldr x0, [x1] // x0 = *(int64_t*)x1str x0, [x1] // *(int64_t*)x1 = x0ldr x0, [x1, #8] // load from x1 + 8 (offset)ldr x0, [x1, #8]! // pre-index: x1 += 8, then loadldr x0, [x1], #8 // post-index: load, then x1 += 8ldp x0, x1, [sp] // load pair (common for prologue/epilogue)stp x0, x1, [sp, #-16]! // store pair, pre-decrement sp by 16ldrb w0, [x1] // load byte, zero-extend into w0ldrsw x0, [x1] // load 32-bit signed, sign-extend to x0adr x0, label // PC-relative address of labeladrp x0, label // page address (paired with add for full addr)
Branches & Function Calls
Conditional branches and the call/return pattern.
asm
cmp x0, x1b.eq equal_label // branch if equalb.lt less_label // branch if less than (signed)b.ne not_equal_label // branch if not equalb loop_start // unconditional branchbl my_function // branch and link: x30 = return addr, jumpret // return: jumps to address in x30 (LR)my_function: stp x29, x30, [sp, #-16]! // save frame pointer + link register mov x29, sp // set up frame pointer // ... body, x0-x7 hold args, x0 holds return value ... ldp x29, x30, [sp], #16 // restore ret
Linux Syscall Convention
How to invoke a Linux syscall directly on AArch64.
- x8- syscall number goes here
- x0-x5- syscall arguments, in order
- svc #0- the instruction that triggers the syscall
- x0 (return)- syscall return value (or negative errno)
- exit example- mov x8,#93; mov x0,#0; svc #0
Pro Tip
Remember AAPCS64 requires the stack pointer to be 16-byte aligned at every public function boundary — misaligned sp on a call to libc or the kernel is a classic, hard-to-debug crash source.
Was this cheat sheet helpful?
Explore Topics
#ARMAssembly#ARMAssemblyCheatSheet#Programming#Advanced#AArch64Registers#DataProcessing#LoadStoreAddressing#BranchesFunctionCalls#Functions#CheatSheet#SkillVeris