04 — Setting Up the Environment¶
Before writing assembly, you need an assembler, linker, and debugger installed and configured.
Required Tools¶
| Tool | Purpose |
|---|---|
nasm |
Netwide Assembler — converts .asm → .o |
ld |
GNU Linker — converts .o → executable |
gdb |
GNU Debugger — step through assembly |
objdump |
Disassemble and inspect object files |
strace |
Trace system calls at runtime |
readelf |
Inspect ELF file headers and sections |
Installation¶
Ubuntu / Debian / WSL2¶
Fedora / RHEL¶
Arch Linux¶
macOS (Homebrew — note: macOS uses Mach-O, not ELF)¶
macOS uses different syscall numbers and binary format. Most examples in this series target Linux ELF. Use WSL2 or a Linux VM for full compatibility.
Windows — WSL2 (Recommended)¶
Then install tools inside the WSL2 terminal as above.Verify Installation¶
nasm --version # NASM version 2.15.x
ld --version # GNU ld (Binutils) 2.38
gdb --version # GNU gdb 12.x
objdump --version # GNU objdump 2.38
Project Directory Structure¶
Organize your assembly projects:
asm-projects/
├── 01-hello/
│ ├── hello.asm
│ └── Makefile
├── 02-registers/
│ ├── registers.asm
│ └── Makefile
└── lib/
└── print.asm (reusable routines)
Your First Program: Hello, World!¶
Create hello.asm:
; hello.asm — print "Hello, World!" to stdout
; Build: nasm -f elf64 hello.asm -o hello.o && ld hello.o -o hello
section .data
msg db "Hello, World!", 10 ; string + newline (0x0A)
len equ $ - msg ; length = current address minus msg address
section .text
global _start ; entry point must be exported
_start:
; sys_write(fd=1, buf=msg, count=len)
mov rax, 1 ; syscall number: sys_write
mov rdi, 1 ; file descriptor: 1 = stdout
mov rsi, msg ; pointer to string
mov rdx, len ; number of bytes to write
syscall ; invoke the kernel
; sys_exit(status=0)
mov rax, 60 ; syscall number: sys_exit
mov rdi, 0 ; exit status 0 = success
syscall
Assemble and Run¶
nasm -f elf64 hello.asm -o hello.o # assemble
ld hello.o -o hello # link
./hello # run
Hello, World!
Inspect the Object File¶
objdump -d hello.o # disassemble
objdump -D hello # disassemble all sections
readelf -h hello # ELF header
readelf -S hello # section headers
Reusable Makefile¶
# Makefile for NASM x86-64 Linux programs
NAME = hello
$(NAME): $(NAME).o
ld $< -o $@
$(NAME).o: $(NAME).asm
nasm -f elf64 $< -o $@
clean:
rm -f $(NAME).o $(NAME)
run: $(NAME)
./$(NAME)
.PHONY: clean run
Usage:
Debugging with GDB¶
GDB lets you step through assembly instruction by instruction.
# Compile with debug info (DWARF)
nasm -f elf64 -g -F dwarf hello.asm -o hello.o
ld hello.o -o hello
# Launch GDB
gdb ./hello
Essential GDB Commands¶
(gdb) set disassembly-flavor intel # use Intel syntax
(gdb) break _start # set breakpoint at entry
(gdb) run # start the program
(gdb) info registers # show all register values
(gdb) info registers rax rdi rsi # show specific registers
(gdb) stepi # execute ONE instruction (si)
(gdb) nexti # step over calls (ni)
(gdb) x/16xb $rsp # examine 16 bytes at RSP (hex)
(gdb) x/4xg $rsp # examine 4 qwords at RSP
(gdb) x/s $rsi # examine memory as string
(gdb) disassemble _start # show disassembly of function
(gdb) display/i $rip # auto-show next instruction
(gdb) quit # exit GDB
GDB TUI Mode (Text UI)¶
Or press Ctrl+X A inside GDB to toggle the split view showing source/disassembly and registers side by side.
Useful objdump Commands¶
# Disassemble the .text section with Intel syntax
objdump -d -M intel hello
# Show all sections with content
objdump -D -M intel hello
# Show section headers
objdump -h hello
# Show symbol table
objdump -t hello
# Dump hex + ASCII of .data section
objdump -s -j .data hello
strace — Trace System Calls¶
Output:
This confirms exactly which syscalls your program makes — invaluable for debugging.
NASM Flags Reference¶
| Flag | Meaning |
|---|---|
-f elf64 |
Output format: 64-bit ELF (Linux) |
-f elf32 |
Output format: 32-bit ELF |
-f macho64 |
Output format: 64-bit Mach-O (macOS) |
-g |
Include debug information |
-F dwarf |
Use DWARF debug format |
-l hello.lst |
Generate listing file |
-o output.o |
Specify output filename |
-E |
Preprocess only (expand macros) |
-w+all |
Enable all warnings |
Common Errors¶
| Error | Cause | Fix |
|---|---|---|
error: label or instruction expected |
Missing section declaration | Add section .text |
ld: cannot find entry symbol _start |
Missing global _start |
Add global _start |
Segmentation fault |
Jumped to invalid address | Check RIP with GDB |
nasm: error: invalid combination of opcode and operands |
Wrong register size | Use matching register names |