Assembly#
Assembly is the operator’s view of the machine. Each instruction maps one-for-one to a CPU opcode; there are no abstractions to peel back. Write assembly when the higher-level language has no way to express what the CPU needs (atomic primitives, syscall wrappers, boot code, exploit primitives) and reads it constantly during reverse engineering, exploit development, and crash analysis.
For the operator, the everyday targets are x86-64
(x86_64 / amd64) on Linux and Windows, and ARM64
(aarch64) on macOS, Linux, and modern embedded. Both are
RISC-shaped in usage even if x86-64 is a CISC instruction set
underneath.
Baseline. GAS (AT&T or Intel syntax through .intel_syntax),
NASM, and the C compiler’s inline asm are the operator’s
three entry points. Disassembly views (objdump -d,
radare2, Ghidra) lean Intel syntax; write
in the syntax that matches the toolchain.
Default toolchain. gcc / clang (as both compiler
and assembler driver), nasm (for Intel-syntax standalone),
ld, objdump, nm, readelf, gdb /
gef, radare2, Ghidra.
Setup#
Picking an assembler and getting the toolchain on the host.
gcc, clang, nasm, yasm, as, ld,
make. Picking syntax and bootstrapping a build.
nasm, as, objdump, nm, readelf,
strings, gdb / gef, radare2,
Ghidra, capstone, keystone.
Common x86-64 patterns: zero register, syscall, stack
align, rdtsc, cpuid, memory fence.
Language#
The building blocks.
AT&T vs Intel, comments (; / # / //),
labels, directives (.data, .text, .global),
sections.
x86-64: rax rbx rcx rdx rsi rdi rbp rsp r8..r15;
ARM64: x0..x30 sp. Stack frame, callee- vs
caller-saved.
Sizes (byte word dword qword / b h w x),
signed vs unsigned, alignment, layout, addressing
modes.
mov add sub mul div, and or xor not shl shr,
cmp test, inc dec, lea. The arithmetic,
logical, and addressing mnemonics.
Flags (ZF SF CF OF), cmp / test, jmp je
jne jl jg jb ja jc jnc, call / ret, loop.
Calling conventions (SysV AMD64, AArch64 AAPCS,
Microsoft x64), call / ret, stack frames,
prologue / epilogue, leaf vs non-leaf.
No classes. Structs as offsets, vtables as arrays of
function pointers, dispatch via call qword ptr
[vtable+8*idx].
Patterns#
The layer above the spec.
Stack-canary checks, PIC / PIE, GOT / PLT, ROP gadgets, shellcode structure, position-independent payloads.
Faults (SIGSEGV, SIGILL, SIGFPE),
syscall errno convention, exception tables,
sanity-check idioms.
Data Structures#
The structures build out of memory.
Arrays, structs, linked lists, stacks. Layout, padding, alignment.
memcpy, strlen, SIMD (SSE / AVX / NEON),
hand-rolled loops, popcnt, the operator’s hot-path
kit.
I/O#
Talking to the kernel and the user.
Syscall conventions (syscall on x86-64 Linux,
svc #0 on ARM64), read / write /
open, format strings via libc.
_start, main, argc / argv from the
stack, exit syscall, exit codes.
Socket syscalls (socket, connect, bind),
shellcode reverse / bind shell forms.
lock prefix, cmpxchg, xchg, mfence /
lfence / sfence, pause, rdtsc.
Runtime#
The compile-link-load model and what happens between source and the running process.
ELF format, _start, dynamic loader (ld.so),
crt0, ABI, PIE / ASLR, relocations, sections vs
segments.
Ecosystem#
The libraries and frameworks the operator pulls in.
libc (glibc / musl), syscall wrappers,
Capstone (disassembler), Keystone (assembler),
Unicorn (CPU emulator).
pwntools, Metasploit pattern / shellcode generator,
ROPgadget, radare2 / Ghidra scripting APIs,
angr for symbolic execution.
Practice#
The disciplines that keep hand-written assembly correct.
Unit-testing assembly through C wrappers, gdb
scripting, unicorn for emulation, side-channel
analysis with rdtsc.
End-to-end projects: a syscall-only hello world, a
reverse shell payload, a kernel-mode probe, a ROP
chain.