07 — Basic Instructions¶
This module covers the core instruction set: data movement, arithmetic, and logic. These form the building blocks of every assembly program.
Data Transfer Instructions¶
MOV — Move (Copy)¶
The most common instruction. Copies a value from source to destination.
mov rax, 42 ; register ← immediate
mov rax, rbx ; register ← register
mov rax, [rbx] ; register ← memory
mov [rbx], rax ; memory ← register
mov [rbx], 0 ; memory ← immediate (size must be clear)
mov dword [rbx], 0
Rules: - Destination and source cannot both be memory references - Source and destination must be the same size
MOVZX — Move with Zero Extension¶
Copies a smaller value into a larger register, filling upper bits with zeros.
movzx rax, byte [rsi] ; rax = zero_extend(*(u8*)rsi)
movzx rax, word [rsi] ; rax = zero_extend(*(u16*)rsi)
movzx rax, bl ; rax = zero_extend(bl)
MOVSX — Move with Sign Extension¶
Copies a smaller value, filling upper bits with the sign bit (two's complement).
movsx rax, byte [rsi] ; rax = sign_extend(*(i8*)rsi)
movsx rax, word [rsi] ; rax = sign_extend(*(i16*)rsi)
movsx rax, ebx ; rax = sign_extend(ebx) (32→64)
movsxd rax, ebx ; same as above (explicit 32→64 mnemonic)
XCHG — Exchange¶
Atomically swap two values (one can be memory). Useful for spin locks.
CMOVcc — Conditional Move¶
Move only if condition is true. Avoids branch mispredictions.
cmp rax, rbx
cmove rax, rcx ; if ZF=1 (equal), rax = rcx
cmovne rax, rcx ; if ZF=0 (not equal)
cmovl rax, rcx ; if SF≠OF (less than, signed)
cmovg rax, rcx ; if ZF=0 and SF=OF (greater than, signed)
Arithmetic Instructions¶
ADD — Addition¶
Sets: CF (carry/overflow), ZF (zero), SF (sign), OF (signed overflow)
SUB — Subtraction¶
CF is set if a borrow occurred (unsigned underflow).
INC / DEC — Increment / Decrement¶
Note: INC/DEC don't update CF, which is why some code prefers
add rax, 1in loops.
MUL — Unsigned Multiply¶
mul rbx ; RDX:RAX = RAX * RBX (128-bit result)
mul ecx ; EDX:EAX = EAX * ECX (64-bit result)
mul cx ; DX:AX = AX * CX (32-bit result)
The source is always the implicit RAX (or EAX, AX, AL). Result spans two registers.
IMUL — Signed Multiply¶
IMUL has three forms:
; 1-operand: RDX:RAX = RAX * src (like MUL but signed)
imul rbx
; 2-operand: dst = dst * src (truncated to register width)
imul rax, rbx ; rax *= rbx
imul rax, 7 ; rax *= 7
; 3-operand: dst = src1 * src2 (truncated)
imul rax, rbx, 10 ; rax = rbx * 10
The 2- and 3-operand forms are most commonly used because the result stays in one register.
DIV — Unsigned Divide¶
; For 64-bit: RDX:RAX ÷ src → quotient=RAX, remainder=RDX
xor rdx, rdx ; MUST zero RDX before dividing!
mov rax, 100
mov rbx, 7
div rbx ; rax = 100/7 = 14, rdx = 100%7 = 2
Division by zero triggers a #DE (Divide Error) exception — program crash.
IDIV — Signed Divide¶
; RDX:RAX ÷ src → quotient=RAX, remainder=RDX
; Sign-extend RAX into RDX first:
cqo ; sign-extend RAX → RDX:RAX (Convert Quadword to Octaword)
mov rbx, -7
idiv rbx
Sign-extension instructions:
| Instruction | Effect |
|---|---|
cbw |
Sign-extend AL → AX |
cwde |
Sign-extend AX → EAX |
cdqe |
Sign-extend EAX → RAX |
cwd |
Sign-extend AX → DX:AX |
cdq |
Sign-extend EAX → EDX:EAX |
cqo |
Sign-extend RAX → RDX:RAX |
NEG — Negate (Two's Complement)¶
Equivalent to not rax; add rax, 1.
Logic Instructions¶
AND, OR, XOR¶
and rax, rbx ; rax = rax & rbx (bitwise AND)
or rax, rbx ; rax = rax | rbx (bitwise OR)
xor rax, rbx ; rax = rax ^ rbx (bitwise XOR)
Common idioms:
xor rax, rax ; rax = 0 (faster/smaller than mov rax, 0)
and rax, 0x0F ; keep only the low nibble
or rax, 0x20 ; set bit 5 (lowercase a letter)
xor rax, 0xFF ; toggle the low byte
NOT — Bitwise Complement¶
TEST — Bitwise AND Without Storing¶
TEST performs AND and sets flags but discards the result. Used for comparisons.
test rax, rax ; is rax zero? (ZF=1 if zero)
test rax, 1 ; is bit 0 set? (ZF=0 if set)
test al, 0x80 ; is the sign bit set?
CMP — Compare (Subtraction Without Storing)¶
CMP subtracts src from dst and sets flags but discards the result.
cmp rax, rbx ; sets flags as if: rax - rbx
cmp rax, 0 ; compare with zero
cmp rax, -1 ; compare with -1
After CMP, use a conditional jump:
cmp rax, 10
je equal_label ; jump if rax == 10 (ZF=1)
jne neq_label ; jump if rax != 10 (ZF=0)
jl less_label ; jump if rax < 10 (signed)
jg greater_label ; jump if rax > 10 (signed)
jle le_label ; jump if rax <= 10 (signed)
jge ge_label ; jump if rax >= 10 (signed)
jb below_label ; jump if rax < 10 (unsigned)
ja above_label ; jump if rax > 10 (unsigned)
Shift Instructions¶
SHL / SHR — Shift Left / Right (Logical)¶
shl rax, 1 ; rax <<= 1 (multiply by 2)
shl rax, 3 ; rax <<= 3 (multiply by 8)
shr rax, 1 ; rax >>= 1 (divide by 2, unsigned)
shr rax, cl ; shift amount in CL register
SHL fills with 0 bits on the right. SHR fills with 0 bits on the left.
SAR — Shift Arithmetic Right (Signed)¶
SAR fills with the sign bit (MSB), preserving the sign for negative numbers.
ROL / ROR — Rotate Left / Right¶
Bits rotate around — nothing is lost, just moved.
NOP — No Operation¶
Used for alignment, timing padding, or as placeholder for patching.
Complete Example: Integer Math¶
; math.asm — demonstrate arithmetic instructions
section .data
a dq 100
b dq 37
section .text
global _start
_start:
; Load values
mov rax, [a] ; rax = 100
mov rbx, [b] ; rbx = 37
; Addition
mov rcx, rax
add rcx, rbx ; rcx = 137
; Subtraction
mov rdx, rax
sub rdx, rbx ; rdx = 63
; Multiplication (2-operand IMUL)
imul rax, rbx ; rax = 100 * 37 = 3700
; Division: 100 / 37
mov rax, [a]
xor rdx, rdx
mov rbx, [b]
div rbx ; rax = 2 (quotient), rdx = 26 (remainder)
; Bitwise: mask lower byte
mov rax, 0xDEADBEEF
and eax, 0xFF ; eax = 0xEF
; Fast multiply by 5 using LEA
mov rax, 10
lea rax, [rax + rax*4] ; rax = 10 + 10*4 = 50
; Exit
mov rax, 60
xor rdi, rdi
syscall
Key Takeaways¶
| Instruction | Effect |
|---|---|
mov dst, src |
Copy value |
movzx dst, src |
Copy with zero-extension |
movsx dst, src |
Copy with sign-extension |
add/sub dst, src |
Arithmetic, sets flags |
imul dst, src |
Signed multiply (2-operand) |
div/idiv src |
RDX:RAX ÷ src; always zero/sign-extend RDX first |
and/or/xor dst, src |
Bitwise logic |
test dst, src |
Bitwise AND, sets flags only |
cmp dst, src |
Subtract, sets flags only |
shl/shr/sar dst, n |
Shift (logical/arithmetic) |
xor rax, rax |
Fastest way to zero a register |