NASM & x86-64 ASSEMBLY

NASM Assembly Language: A Practical Guide to x86-64 Programming.

Understand NASM from the ground up — from registers and instructions to memory addressing, stacks, procedures, Linux system calls, and debugging. This guide is designed to make low-level programming easier to understand, explain, and apply.

NASM fundamentals

What is NASM?

NASM, the Netwide Assembler, is an assembler used to translate human-readable assembly language into machine code. It is widely used for x86 and x86-64 programming and is particularly useful for understanding how software interacts with processors at a low level.

Assembly language sits much closer to the processor than languages such as Python, Java, or C. Instead of expressing a task through high-level abstractions, assembly exposes operations such as moving values between registers, performing arithmetic, comparing values, accessing memory, manipulating the stack, and transferring control between instructions.

NASM provides a clear and widely used syntax for writing this type of code. It is especially valuable for students and developers studying computer architecture, operating systems, cybersecurity, reverse engineering, compiler concepts, and low-level software development.

This page serves as the main NASM guide in the ProjectAssignments technology library. The supporting pages below go deeper into specific parts of x86-64 assembly.

Why NASM matters

Why learn assembly language when high-level languages exist?

Assembly is not normally the fastest way to build everyday software, but it provides a level of visibility into computer operation that high-level languages intentionally hide.

Understand the processor

Assembly provides a practical way to understand registers, instructions, flags, the instruction pointer, memory, and the relationship between software and CPU execution.

Understand memory

Concepts such as addresses, pointers, stack frames, offsets, and addressing modes become much more concrete when working directly with memory operands.

Study operating systems

Low-level programming helps explain system calls, process execution, calling conventions, stack management, and the boundary between applications and the operating system.

Explore cybersecurity

Assembly knowledge is particularly useful for reverse engineering, binary analysis, vulnerability research, debugging, malware analysis, and understanding compiled programs.

The x86-64 foundation

Understanding the environment before writing NASM code.

Modern NASM work often targets the x86-64 architecture. Before learning individual instructions, it helps to understand the basic components that an assembly program interacts with.

Registers

Registers are small, extremely fast storage locations inside the processor. x86-64 provides a collection of general purpose and specialised registers that are used for values, addresses, stack management, control flow, and processor state.

Memory

Data that cannot or should not remain exclusively in registers is stored in memory. NASM lets programmers access memory through different addressing forms, making memory addressing one of the most important concepts in assembly.

Instruction pointer

The instruction pointer identifies the location associated with the next instruction to be executed. In x86-64 this is represented by RIP, the 64-bit instruction pointer register.

Flags

The processor maintains status information through flags. Instructions such as comparison and arithmetic operations can affect these flags, which are then used by conditional branches and other instructions.

Registers & instructions

The building blocks of NASM programs.

Most introductory NASM programs can be understood by learning how values move through registers and memory, how instructions transform those values, and how control flow changes the order of execution.

Common x86-64 registers

RegisterTypical role
RAXAccumulator and common return-value register
RBXGeneral-purpose register
RCXGeneral-purpose and counting-related operations
RDXGeneral-purpose and arithmetic/data operations
RSIGeneral-purpose register and source-related operations
RDIGeneral-purpose register and destination-related operations
RSPStack pointer
RBPCommonly used as a stack-frame base pointer
RIPInstruction pointer
R8–R15Additional general-purpose registers

Frequently encountered instructions

NASM programs are constructed from instructions. Some of the most important instructions for beginners include:

  • MOV — transfers data between registers, memory, and immediate values.
  • ADD / SUB — perform arithmetic operations.
  • INC / DEC — increment or decrement values.
  • CMP — compares operands and updates processor flags.
  • JMP — performs an unconditional jump.
  • JE / JNE / JL / JG — perform conditional control-flow operations.
  • PUSH / POP — interact with the stack.
  • CALL / RET — support procedure calls and returns.
  • AND / OR / XOR — perform bitwise logical operations.
  • SHL / SHR — shift bits left or right.

A simple example

Reading a NASM program.

A small program is often the best way to understand the relationship between registers, instructions, labels, and control flow.

section .text
    global _start

_start:
    mov rax, 60
    mov rdi, 0
    syscall

Even this short example introduces several important concepts. The section .text directive identifies the section containing executable instructions, while global makes the entry symbol visible to the linker.

The mov instructions place values into registers. The final syscall instruction transfers control to the operating system's system-call mechanism.

The important lesson is not simply memorising the code. A strong understanding of NASM comes from knowing why each register is being used, how the operating system interprets those registers, and what happens to the processor state when the instruction executes.

Memory & addressing

Where assembly becomes genuinely interesting.

Moving values between registers is only part of assembly programming. Understanding how instructions locate data in memory is essential for writing meaningful x86-64 programs.

Addresses and values

An address identifies a location in memory, while the value stored at that location is the data itself. Confusing these two concepts is one of the most common difficulties for beginners.

Addressing modes

x86-64 supports several ways of constructing memory operands. Registers can be combined with offsets, base addresses, and index registers to locate data efficiently.

Memory operands

NASM uses square brackets to indicate memory access. This distinction is fundamental because moving a register's value is different from accessing the memory location represented by that register.

Why it matters

Correct memory addressing is essential when working with arrays, structures, buffers, strings, stack frames, and dynamically managed data.

Our dedicated guide will explore x86-64 memory addressing and stack management in considerably more detail.

Explore NASM memory addressing and the stack →

The stack & procedures

Understanding CALL, RET, PUSH, POP, RSP and RBP.

The stack is central to procedure calls, temporary storage, saved state, and stack frames. Understanding it makes many otherwise confusing assembly programs much easier to follow.

The stack is a region of memory managed through the stack pointer. In x86-64, RSP identifies the current stack position. Instructions such as PUSH and POP modify the stack, while CALL and RET provide a mechanism for entering and leaving procedures.

RBP is also commonly encountered when studying traditional stack-frame layouts. Although modern compilers can use registers differently depending on optimisation and calling conventions, learning the conventional RSP/RBP model provides a useful foundation.

Once these concepts are understood, topics such as local variables, function parameters, return addresses, and debugging stack frames become much easier to understand.

Learn more about memory, stacks and addressing →

Linux & system calls

NASM beyond individual instructions.

Writing useful assembly programs requires understanding how the program interacts with the operating system.

On Linux x86-64, applications can request operating-system services through system calls. Registers are used to identify the requested operation and provide the relevant arguments.

This introduces an important distinction between an assembly instruction and an operating-system service. An instruction is executed by the processor, while a system call provides a controlled interface through which a user-space program can request functionality from the operating system kernel.

Learning this boundary is particularly useful for students studying operating systems, cybersecurity, systems programming, and reverse engineering.

Explore NASM on Linux, system calls and debugging →

Learning path

A practical route to learning NASM.

NASM becomes much easier when concepts are learned in a logical order rather than as a long list of instructions.

01

Learn computer architecture basics

Understand CPUs, registers, memory, instructions, addresses, and the basic fetch-decode-execute cycle.

02

Master registers and data movement

Begin with MOV and learn how values move between immediate operands, registers, and memory.

03

Learn arithmetic and control flow

Study arithmetic, comparisons, flags, jumps, loops, labels, and conditional execution.

04

Understand memory and the stack

Move from simple register operations into addressing modes, arrays, stack operations, procedures, and stack frames.

05

Work with the operating system

Learn system calls, linking, executable formats, and how user-space programs communicate with the operating system.

06

Debug and analyse programs

Use debugging tools to inspect registers, memory, instructions, stack frames, and program execution.

NASM deep dives

Continue with the supporting guides.

The NASM technology cluster will expand into focused guides so that each major concept can be studied without turning the main page into an unreadable reference manual.

Academic & technical work

NASM is useful far beyond a programming exercise.

Assembly language frequently appears in computer science coursework, systems programming projects, operating-system studies, cybersecurity exercises, and technical research.

A NASM-based assignment or project may require considerably more than writing a few instructions. Students may need to understand processor architecture, explain register usage, document algorithms, interpret memory operations, analyse execution, or connect assembly code with operating-system concepts.

ProjectAssignments provides technical academic guidance, research support, and structured assistance for complex computing work. Our focus is on helping learners understand the technical reasoning behind their work rather than treating technical assignments as simple code-generation exercises.

Explore our technical academic services →

Let's make your work clearer

Bring us the difficult part.

Tell us what you're researching, building, or trying to understand. We'll help you find the clearest ethical next move.

Get Guidance
Chat with us on WhatsApp