Introduction
Assembly language is a low-level programming language that has a strong correspondence between the language’s instructions and the processor’s machine code instructions. This cheat sheet focuses primarily on x86 assembly with notes on other architectures where relevant.
Common Terminology
- Register: CPU’s internal storage locations
- Instruction: A single operation the CPU can perform
- Operand: Data that an instruction operates on
- Addressing Mode: How memory locations are specified
- Mnemonic: Human-readable instruction name
Register Sets
x86 (32-bit) Registers
General Purpose Registers
- EAX: Accumulator (arithmetic operations, function return values)
- EBX: Base (pointer to data in memory)
- ECX: Counter (loop counter)
- EDX: Data (arithmetic operations)
- ESI: Source Index (string operations source)
- EDI: Destination Index (string operations destination)
- ESP: Stack Pointer (points to top of stack)
- EBP: Base Pointer (points to base of stack frame)
Segment Registers
- CS: Code Segment
- DS: Data Segment
- SS: Stack Segment
- ES, FS, GS: Extra Segments
Status Flags (EFLAGS)
- CF: Carry Flag
- ZF: Zero Flag
- SF: Sign Flag
- OF: Overflow Flag
- PF: Parity Flag
- AF: Auxiliary Carry Flag
x86-64 (64-bit) Additional Registers
- RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP: 64-bit extensions of 32-bit registers
- R8-R15: Additional 64-bit registers
- XMM0-XMM15: 128-bit SIMD registers
ARM Registers
- R0-R12: General purpose registers
- R13 (SP): Stack pointer
- R14 (LR): Link register (return address)
- R15 (PC): Program counter
MIPS Registers
- $0: Constant zero
- $1: Reserved for assembler
- $2-$3: Function results
- $4-$7: Function arguments
- $8-$15, $24-$25: Temporaries
- $16-$23: Saved registers
- $26-$27: Reserved for OS
- $28 (GP): Global pointer
- $29 (SP): Stack pointer
- $30 (FP): Frame pointer
- $31 (RA): Return address
Data Movement Instructions
x86/x64
| Instruction | Description | Example |
|---|
MOV | Move data between registers or between register and memory | MOV EAX, EBX |
PUSH | Push value onto stack | PUSH EAX |
POP | Pop value from stack | POP EAX |
XCHG | Exchange values | XCHG EAX, EBX |
LEA | Load effective address | LEA EAX, [EBX+4*ECX+8] |
MOVZX | Move with zero extend | MOVZX EAX, BL |
MOVSX | Move with sign extend | MOVSX EAX, BL |
ARM
| Instruction | Description | Example |
|---|
MOV | Move data | MOV R0, R1 |
LDR | Load from memory | LDR R0, [R1] |
STR | Store to memory | STR R0, [R1] |
PUSH | Push to stack | PUSH {R0-R3, LR} |
POP | Pop from stack | POP {R0-R3, PC} |
MIPS
| Instruction | Description | Example |
|---|
LW | Load word | LW $t0, 4($sp) |
SW | Store word | SW $t0, 4($sp) |
MOVE | Move between registers | MOVE $t0, $t1 |
LI | Load immediate | LI $t0, 42 |
Arithmetic Instructions
x86/x64
| Instruction | Description | Example |
|---|
ADD | Add | ADD EAX, EBX |
SUB | Subtract | SUB EAX, EBX |
MUL | Unsigned multiply | MUL EBX (EAX *= EBX) |
IMUL | Signed multiply | IMUL EAX, EBX, 4 (EAX = EBX * 4) |
DIV | Unsigned divide | DIV EBX (EDX:EAX / EBX) |
IDIV | Signed divide | IDIV EBX (EDX:EAX / EBX) |
INC | Increment | INC EAX |
DEC | Decrement | DEC EAX |
NEG | Negate | NEG EAX |
CMP | Compare | CMP EAX, EBX |
ARM
| Instruction | Description | Example |
|---|
ADD | Add | ADD R0, R1, R2 (R0 = R1 + R2) |
SUB | Subtract | SUB R0, R1, R2 (R0 = R1 – R2) |
MUL | Multiply | MUL R0, R1, R2 (R0 = R1 * R2) |
SDIV | Signed divide | SDIV R0, R1, R2 (R0 = R1 / R2) |
CMP | Compare | CMP R0, R1 |
MIPS
| Instruction | Description | Example |
|---|
ADD | Add | ADD $t0, $t1, $t2 |
ADDI | Add immediate | ADDI $t0, $t1, 42 |
SUB | Subtract | SUB $t0, $t1, $t2 |
MULT | Multiply | MULT $t1, $t2 (result in HI:LO) |
DIV | Divide | DIV $t1, $t2 (result in HI:LO) |
Logical Instructions
x86/x64
| Instruction | Description | Example |
|---|
AND | Bitwise AND | AND EAX, EBX |
OR | Bitwise OR | OR EAX, EBX |
XOR | Bitwise XOR | XOR EAX, EBX |
NOT | Bitwise NOT | NOT EAX |
SHL | Shift left | SHL EAX, 2 |
SHR | Shift right | SHR EAX, 2 |
SAR | Shift arithmetic right | SAR EAX, 2 |
ROL | Rotate left | ROL EAX, 1 |
ROR | Rotate right | ROR EAX, 1 |
TEST | Test bits (AND without storing) | TEST EAX, 1 |
ARM
| Instruction | Description | Example |
|---|
AND | Bitwise AND | AND R0, R1, R2 |
ORR | Bitwise OR | ORR R0, R1, R2 |
EOR | Bitwise XOR | EOR R0, R1, R2 |
MVN | Bitwise NOT | MVN R0, R1 |
LSL | Logical shift left | LSL R0, R1, #2 |
LSR | Logical shift right | LSR R0, R1, #2 |
ASR | Arithmetic shift right | ASR R0, R1, #2 |
MIPS
| Instruction | Description | Example |
|---|
AND | Bitwise AND | AND $t0, $t1, $t2 |
ANDI | Bitwise AND immediate | ANDI $t0, $t1, 42 |
OR | Bitwise OR | OR $t0, $t1, $t2 |
XOR | Bitwise XOR | XOR $t0, $t1, $t2 |
SLL | Shift left logical | SLL $t0, $t1, 2 |
SRL | Shift right logical | SRL $t0, $t1, 2 |
SRA | Shift right arithmetic | SRA $t0, $t1, 2 |
Control Flow Instructions
x86/x64
Unconditional Jumps
| Instruction | Description | Example |
|---|
JMP | Jump to address | JMP label |
CALL | Call procedure | CALL procedure |
RET | Return from procedure | RET |
Conditional Jumps
| Instruction | Description | Condition |
|---|
JE/JZ | Jump if equal / zero | ZF = 1 |
JNE/JNZ | Jump if not equal / not zero | ZF = 0 |
JG/JNLE | Jump if greater (signed) | ZF = 0 and SF = OF |
JGE/JNL | Jump if greater or equal (signed) | SF = OF |
JL/JNGE | Jump if less (signed) | SF ≠OF |
JLE/JNG | Jump if less or equal (signed) | ZF = 1 or SF ≠OF |
JA/JNBE | Jump if above (unsigned) | CF = 0 and ZF = 0 |
JAE/JNB | Jump if above or equal (unsigned) | CF = 0 |
JB/JNAE | Jump if below (unsigned) | CF = 1 |
JBE/JNA | Jump if below or equal (unsigned) | CF = 1 or ZF = 1 |
JC | Jump if carry | CF = 1 |
JNC | Jump if not carry | CF = 0 |
JO | Jump if overflow | OF = 1 |
JNO | Jump if not overflow | OF = 0 |
JS | Jump if sign (negative) | SF = 1 |
JNS | Jump if not sign (positive) | SF = 0 |
ARM
| Instruction | Description | Example |
|---|
B | Branch | B label |
BL | Branch with link (call) | BL function |
BX | Branch and exchange | BX LR (return) |
BEQ | Branch if equal | BEQ label |
BNE | Branch if not equal | BNE label |
BLT | Branch if less than | BLT label |
BGT | Branch if greater than | BGT label |
BLE | Branch if less or equal | BLE label |
BGE | Branch if greater or equal | BGE label |
MIPS
| Instruction | Description | Example |
|---|
J | Jump | J label |
JAL | Jump and link (call) | JAL function |
JR | Jump register (return) | JR $ra |
BEQ | Branch if equal | BEQ $t0, $t1, label |
BNE | Branch if not equal | BNE $t0, $t1, label |
BGTZ | Branch if greater than zero | BGTZ $t0, label |
BLTZ | Branch if less than zero | BLTZ $t0, label |
BGEZ | Branch if greater or equal to zero | BGEZ $t0, label |
BLEZ | Branch if less or equal to zero | BLEZ $t0, label |
Memory Addressing Modes
x86/x64
| Addressing Mode | Syntax Example | Description |
|---|
| Register | MOV EAX, EBX | Operand is in register |
| Immediate | MOV EAX, 42 | Constant value |
| Direct | MOV EAX, [0x1000] | Value at memory address |
| Register Indirect | MOV EAX, [EBX] | Value at address in register |
| Base + Displacement | MOV EAX, [EBX+8] | Value at register + offset |
| Base + Index | MOV EAX, [EBX+ECX] | Value at register + register |
| Base + Index + Displacement | MOV EAX, [EBX+ECX+8] | Value at register + register + offset |
| Scaled Index | MOV EAX, [EBX+4*ECX] | Value at register + (register * scale) |
| Scaled Index + Displacement | MOV EAX, [EBX+4*ECX+8] | Value at register + (register * scale) + offset |
ARM
| Addressing Mode | Syntax Example | Description |
|---|
| Register | MOV R0, R1 | Operand is in register |
| Immediate | MOV R0, #42 | Constant value |
| Register Indirect | LDR R0, [R1] | Value at address in register |
| Pre-indexed | LDR R0, [R1, #4]! | Value at address in register + offset, base updated |
| Post-indexed | LDR R0, [R1], #4 | Value at address in register, base updated after |
| PC Relative | LDR R0, [PC, #12] | Value at PC + offset |
MIPS
| Addressing Mode | Syntax Example | Description |
|---|
| Register | ADD $t0, $t1, $t2 | Operand is in register |
| Immediate | ADDI $t0, $t1, 42 | Constant value |
| Base + Displacement | LW $t0, 4($t1) | Value at register + offset |
SIMD Instructions (x86/x64)
SSE/AVX Registers
- XMM0-XMM15: 128-bit registers
- YMM0-YMM15: 256-bit registers (AVX)
- ZMM0-ZMM31: 512-bit registers (AVX-512)
Common SSE Instructions
| Instruction | Description | Example |
|---|
MOVAPS | Move aligned packed single precision | MOVAPS XMM0, XMM1 |
MOVUPS | Move unaligned packed single precision | MOVUPS XMM0, [EAX] |
ADDPS | Add packed single precision | ADDPS XMM0, XMM1 |
SUBPS | Subtract packed single precision | SUBPS XMM0, XMM1 |
MULPS | Multiply packed single precision | MULPS XMM0, XMM1 |
DIVPS | Divide packed single precision | DIVPS XMM0, XMM1 |
SQRTPS | Square root of packed single precision | SQRTPS XMM0, XMM1 |
MAXPS | Maximum of packed single precision | MAXPS XMM0, XMM1 |
MINPS | Minimum of packed single precision | MINPS XMM0, XMM1 |
Common AVX Instructions
| Instruction | Description | Example |
|---|
VMOVAPS | Move aligned packed single precision | VMOVAPS YMM0, YMM1 |
VADDPS | Add packed single precision | VADDPS YMM0, YMM1, YMM2 |
VSUBPS | Subtract packed single precision | VSUBPS YMM0, YMM1, YMM2 |
VMULPS | Multiply packed single precision | VMULPS YMM0, YMM1, YMM2 |
VDIVPS | Divide packed single precision | VDIVPS YMM0, YMM1, YMM2 |
System Instructions
x86/x64
| Instruction | Description | Example |
|---|
INT | Call to interrupt | INT 0x80 (Linux syscall, legacy) |
SYSCALL | System call (64-bit) | SYSCALL |
SYSENTER | Fast system call | SYSENTER |
IN | Input from port | IN AL, 0x60 |
OUT | Output to port | OUT 0x60, AL |
CLI | Clear interrupt flag | CLI |
STI | Set interrupt flag | STI |
HLT | Halt processor | HLT |
CPUID | CPU identification | CPUID |
String Operations (x86/x64)
| Instruction | Description |
|---|
MOVS | Move string |
CMPS | Compare string |
SCAS | Scan string |
LODS | Load string |
STOS | Store string |
REP | Repeat prefix (repeat until ECX = 0) |
REPE/REPZ | Repeat while equal/zero |
REPNE/REPNZ | Repeat while not equal/not zero |
Common x86/x64 Calling Conventions
cdecl (C Declaration)
- Arguments pushed on stack from right to left
- Caller cleans the stack
- EAX, ECX, EDX are caller-saved
- Other registers are callee-saved
- Return value in EAX
stdcall (Standard Call)
- Arguments pushed on stack from right to left
- Callee cleans the stack
- Return value in EAX
fastcall
- First two arguments in ECX and EDX
- Remaining arguments pushed on stack from right to left
- Callee cleans the stack
- Return value in EAX
x64 (Microsoft)
- First four arguments in RCX, RDX, R8, R9
- Additional arguments pushed on stack from right to left
- 32 bytes of shadow space on stack
- Return value in RAX
x64 (System V – Linux, macOS)
- First six integer/pointer arguments in RDI, RSI, RDX, RCX, R8, R9
- First eight floating-point arguments in XMM0-XMM7
- Additional arguments pushed on stack from right to left
- Return value in RAX (integer) or XMM0 (floating-point)
Common Assembler Directives
General Directives
| Directive | Description |
|---|
.data | Start data section |
.text | Start code section |
.global / .globl | Make symbol global |
.extern | Declare external symbol |
.equ / .set | Define constant |
.include | Include file |
.macro | Define macro |
.endm | End macro definition |
.if | Conditional assembly |
.endif | End conditional assembly |
Data Definition Directives
| Directive | Description |
|---|
.byte | Define byte |
.word | Define word (2 bytes) |
.long / .int | Define long (4 bytes) |
.quad | Define quadword (8 bytes) |
.float | Define single precision float |
.double | Define double precision float |
.ascii | Define ASCII string (no null terminator) |
.asciz / .string | Define ASCII string with null terminator |
.space / .skip | Reserve space |
.align | Align to boundary |
Common Assembly Tasks (x86/x64)
Function Prologue (x86)
function:
push ebp ; Save old base pointer
mov ebp, esp ; Set new base pointer
sub esp, X ; Allocate X bytes of local variables
push ebx ; Save callee-saved registers
push esi
push edi
; Function body
Function Epilogue (x86)
pop edi ; Restore callee-saved registers
pop esi
pop ebx
mov esp, ebp ; Deallocate local variables
pop ebp ; Restore old base pointer
ret ; Return to caller
Function Prologue (x64, Microsoft)
function:
push rbp ; Save old base pointer
mov rbp, rsp ; Set new base pointer
sub rsp, X ; Allocate X bytes of local variables (X must be multiple of 16)
; Save non-volatile registers if used
; Function body
Function Epilogue (x64, Microsoft)
; Restore non-volatile registers if saved
mov rsp, rbp ; Deallocate local variables
pop rbp ; Restore old base pointer
ret ; Return to caller
Memory Access Examples (x86)
; Accessing function parameters (cdecl)
mov eax, [ebp+8] ; First parameter
mov ecx, [ebp+12] ; Second parameter
; Accessing local variables
mov [ebp-4], eax ; First local variable
mov [ebp-8], ecx ; Second local variable
; Array indexing (array of 4-byte elements)
mov eax, [ebx+ecx*4] ; array[ecx]
Memory Access Examples (x64, Microsoft)
; Parameters already in registers: RCX, RDX, R8, R9
; Accessing parameters beyond the first four
mov rax, [rbp+16] ; Fifth parameter
; Accessing local variables
mov [rbp-8], rax ; First local variable
mov [rbp-16], rcx ; Second local variable
C-Style Array Access (x86)
; Accessing array[i] where each element is 4 bytes
; Assume:
; - EBX points to the array (array base address)
; - ECX contains i (the index)
; Method 1: Use scaled indexed addressing
mov eax, [ebx+ecx*4] ; Load array[i] into EAX
; Method 2: Calculate address manually
mov eax, ecx ; Copy i to EAX
shl eax, 2 ; Multiply by 4 (size of each element)
add eax, ebx ; Add to base address
mov eax, [eax] ; Load array[i] into EAX
Loop Structure (x86)
mov ecx, 10 ; Initialize counter
loop_start:
; Loop body
dec ecx ; Decrement counter
jnz loop_start ; Jump if not zero
Loop Structure with array (x86)
mov ecx, 10 ; Array length
mov eax, 0 ; Sum
mov esi, array ; Array pointer
loop_start:
add eax, [esi] ; Add current element to sum
add esi, 4 ; Move to next element
dec ecx ; Decrement counter
jnz loop_start ; Jump if not zero
Floating-Point Operations (x87 FPU)
| Instruction | Description | Example |
|---|
FLD | Load floating-point value | FLD DWORD PTR [EAX] |
FST | Store floating-point value | FST DWORD PTR [EAX] |
FSTP | Store floating-point value and pop | FSTP DWORD PTR [EAX] |
FADD | Add floating-point | FADD ST, ST(1) |
FSUB | Subtract floating-point | FSUB ST, ST(1) |
FMUL | Multiply floating-point | FMUL ST, ST(1) |
FDIV | Divide floating-point | FDIV ST, ST(1) |
FCOM | Compare floating-point | FCOM ST(1) |
FSIN | Sine | FSIN |
FCOS | Cosine | FCOS |
FSQRT | Square root | FSQRT |
Tips and Best Practices
- Comment your code: Assembly is difficult to read and understand
- Use meaningful labels: Makes the code more readable
- Be consistent with naming conventions: Helps with maintenance
- Save/restore registers: Especially in functions and interrupts
- Align your data: For performance and to avoid bus errors
- Use macros for repetitive tasks: Reduces code duplication
- Avoid self-modifying code: Hard to maintain and may not work on modern systems
- Use higher-level constructs when available: Many assemblers support structured programming
- Be careful with overflow and boundary conditions: Assembly provides minimal protection
- Test thoroughly: Assembly errors can be subtle and difficult to find
Resources and References
- Intel® 64 and IA-32 Architectures Software Developer Manuals
- ARM Architecture Reference Manual
- MIPS Architecture Reference Manual
- AMD64 Architecture Programmer’s Manual
- “Assembly Language for x86 Processors” by Kip Irvine
- “Programming from the Ground Up” by Jonathan Bartlett
- “Art of Assembly Language” by Randall Hyde