π Topic 1: Setup & First Program
Welcome to your first assembly lesson! Letβs get you set up and writing your first NASM program.
Part 1: Installation
Check if NASM is already installed:
nasm -version
If not installed, install it:
# Red Hat/CentOS/Rocky
sudo yum install nasm
# Or if you have dnf
sudo dnf install nasm
# You'll also need a linker (gcc provides ld)
sudo yum install gcc
Part 2: The Assembly Workflow
Understanding the build process:
βββββββββββββββ
β hello.asm β β Your source code (human-readable)
ββββββββ¬βββββββ
β nasm -f elf64 hello.asm
βΌ
βββββββββββββββ
β hello.o β β Object file (machine code, not executable yet)
ββββββββ¬βββββββ
β ld -o hello hello.o
βΌ
βββββββββββββββ
β hello β β Executable (ready to run!)
βββββββββββββββ
Part 3: Program Structure
NASM programs have three main sections:
.data section - Initialized data (variables with values)
section .data
message db "Hello", 0 ; Define byte(s), null-terminated
number dd 42 ; Define doubleword (32-bit)
.bss section - Uninitialized data (reserved space)
section .bss
buffer resb 64 ; Reserve 64 bytes
counter resd 1 ; Reserve 1 doubleword
.text section - Your actual code
section .text
global _start ; Entry point for linker
_start:
; Your instructions here
mov eax, 1 ; Exit syscall
xor ebx, ebx ; Return 0
int 0x80 ; Call kernel
Part 4: Your First Program - Hello World
C Equivalent:
#include <unistd.h>
int main() {
const char *msg = "Hello, Assembly!\n";
size_t msg_len = 17;
// Write to stdout
write(1, msg, msg_len);
// Exit with code 0
return 0;
}
Create a file called hello.asm:
; hello.asm - My first NASM program!
; This program prints "Hello, Assembly!" to the console
section .data
; Define our message with a newline at the end
msg db "Hello, Assembly!", 10 ; 10 is newline character '\n'
msg_len equ $ - msg ; Calculate length (current pos - start)
section .text
global _start
_start:
; Write message to stdout
; syscall: sys_write (rax = 1)
; rdi = file descriptor (1 = stdout)
; rsi = pointer to message
; rdx = message length
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 = stdout
mov rsi, msg ; address of message
mov rdx, msg_len ; length of message
syscall ; make the system call
; Exit program
; syscall: sys_exit (rax = 60)
; rdi = exit code
mov rax, 60 ; syscall number for sys_exit
xor rdi, rdi ; exit code 0 (success)
syscall ; make the system call
Part 5: Build and Run
Step 1: Assemble (convert .asm to .o)
nasm -f elf64 hello.asm -o hello.o
-f elf64: output format for 64-bit Linux-o hello.o: output filename
Step 2: Link (convert .o to executable)
ld -o hello hello.o
-o hello: output executable name
Step 3: Run
./hello
You should see:
Hello, Assembly!
Check exit code:
echo $?
Should print 0 (success)
Part 6: Understanding the Code
Line-by-Line Breakdown:
msg db "Hello, Assembly!", 10
msg= label (like a variable name)db= Define Byte (allocates bytes in memory)10= ASCII code for newline
msg_len equ $ - msg
equ= equate (like#definein C)$= current position in memory$ - msg= length of message
mov rax, 1
- Move value
1into registerrax - In Linux, syscall number 1 =
write
syscall
- Transfers control to the kernel
- Kernel looks at
raxto know which syscall to execute
Part 7: 32-bit Version (Alternative)
C Equivalent (same as 64-bit):
#include <unistd.h>
int main() {
const char *msg = "Hello from 32-bit!\n";
write(1, msg, 19);
return 0;
}
// Note: The C code is identical - the compiler handles 32 vs 64-bit differences
If you want to try 32-bit assembly:
; hello32.asm - 32-bit version
section .data
msg db "Hello from 32-bit!", 10
msg_len equ $ - msg
section .text
global _start
_start:
; sys_write
mov eax, 4 ; syscall 4 = write (32-bit)
mov ebx, 1 ; stdout
mov ecx, msg ; message address
mov edx, msg_len ; message length
int 0x80 ; interrupt (32-bit syscall method)
; sys_exit
mov eax, 1 ; syscall 1 = exit (32-bit)
xor ebx, ebx ; exit code 0
int 0x80
Build 32-bit:
nasm -f elf32 hello32.asm -o hello32.o
ld -m elf_i386 -o hello32 hello32.o
./hello32
Part 8: Common Mistakes & Debugging
β Forgot global _start
ld: warning: cannot find entry symbol _start
Fix: Add global _start in .text section
β Wrong format
hello.o: file not recognized: file format not recognized
Fix: Use -f elf64 for 64-bit or -f elf32 for 32-bit
β Segmentation fault
Segmentation fault (core dumped)
Fix: Check your syscall numbers and register usage
π§ Debug with GDB:
nasm -f elf64 -g -F dwarf hello.asm # Add debug info
ld -o hello hello.o
gdb ./hello
β Practice Exercises
Exercise 1: Modify the Message
Change βHello, Assembly!β to print your name
Exercise 2: Multiple Prints
Print two different messages (hint: call sys_write twice)
Exercise 3: Different Exit Code
Make the program exit with code 42 instead of 0
- Hint: Change the value in
rdibefore the exit syscall - Verify with
echo $?
Exercise 4: No Newline
Remove the newline (the 10) and see what happens to your prompt
Exercise 5: Color Output
Print colored text using ANSI codes:
msg db 27, "[31mRed Text!", 27, "[0m", 10 ; 27 = ESC character
π Quick Reference: Linux 64-bit Syscalls
| Syscall | RAX | RDI | RSI | RDX |
|---|---|---|---|---|
| sys_read | 0 | fd | buffer | count |
| sys_write | 1 | fd | buffer | count |
| sys_exit | 60 | exit_code | - | - |
File Descriptors:
- 0 = stdin (keyboard input)
- 1 = stdout (console output)
- 2 = stderr (error output)
π― Knowledge Check
Before moving to Topic 2, make sure you can:
- β Assemble and link a NASM program
- β
Explain the three sections:
.data,.bss,.text - β
Understand what
syscalldoes - β
Calculate string length with
$ - label - β Successfully run your Hello World program
π Congratulations! Youβve written and executed your first assembly program!
Next: Topic 2: Registers & Data Types
| β Back to Main | Next Topic β |