Assembly Guide — Memory Addressing Modes
In this tutorial, you will learn about Assembly Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
x86-64 memory addressing modes provide flexible ways to calculate memory addresses using combinations of base registers, index registers, scale factors, and displacements.
What You'll Learn
- Direct memory addressing
- Register indirect addressing
- Indexed addressing with scaling
- RIP-relative addressing
- Effective address calculation
Why It Matters
Understanding addressing modes is essential for accessing arrays, structs, and variables in assembly. Durga Antivirus Pro uses these modes for signature scanning.
Real-World Use
Array traversal, struct field access, function parameter access via stack, and position-independent code.
flowchart LR
A["Addressing Modes"] --> B["Direct"]
B --> C["Indirect"]
C --> D["Indexed"]
D --> E["RIP-Relative"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Basic Syntax
; General form: [base + index*scale + displacement]
; base: any GPR (usually RBP, RBX, RSP)
; index: any GPR except RSP (RIP not allowed)
; scale: 1, 2, 4, or 8
; displacement: signed 8/16/32-bit value
mov rax, [rbx] ; [base]
mov rax, [rbx + 16] ; [base + disp]
mov rax, [rbx + rcx] ; [base + index]
mov rax, [rbx + rcx*4] ; [base + index*scale]
mov rax, [rbx + rcx*4 + 8] ; [base + index*scale + disp]
Direct Addressing
; Direct: address is a constant
; Used for static/global variables
section .data
myvar dq 42
section .text
mov rax, [myvar] ; Load from absolute address
mov [myvar], rax ; Store to absolute address
; In 64-bit mode, absolute addressing requires:
mov rax, [rel myvar] ; RIP-relative (default)
mov rax, [abs myvar] ; Absolute (needs linker fixup)
Register Indirect
; Register holds the address
mov rbx, myvar ; RBX = address of myvar
mov rax, [rbx] ; RAX = value at that address
; With displacement (struct access)
mov rax, [rbx + 8] ; Load from myvar + 8
; Negative displacement
mov rax, [rbx - 4] ; Load from myvar - 4
Indexed Addressing
; Used for array access
; [base + index*scale]
section .data
array dq 10, 20, 30, 40, 50
section .text
mov rcx, 2 ; Index 2
mov rax, [array + rcx*8] ; Load array[2] = 30
; Loop through array
xor rcx, rcx
loop:
mov rax, [array + rcx*8] ; array[rcx]
inc rcx
cmp rcx, 5
jl loop
RIP-Relative Addressing
; Default in 64-bit mode
; Address calculated as RIP + displacement
; Enables position-independent code (PIC)
; Assembly uses 'rel' modifier
mov rax, [rel myvar]
; The linker calculates the displacement
; from the current instruction to the variable
; Without 'rel', most assemblers still default to RIP-relative
; for local symbols in .data section
LEA Instruction
; Load Effective Address
; Computes address without accessing memory
lea rax, [rbx + rcx*4 + 16]
; RAX = rbx + rcx*4 + 16 (the address, not the value)
; Useful for arithmetic:
; Multiply by 3: RAX = RBX + RBX*2
lea rax, [rbx + rbx*2]
; Multiply by 5: RAX = RBX + RBX*4
lea rax, [rbx + rbx*4]
; Add constant
lea rax, [rbx + 100]
Common Mistakes
1. Scale factor confusion
Scale can only be 1, 2, 4, or 8. Using other values causes an assembler error.
2. RSP as index register
RSP cannot be used as an index register. Use another register for indexing.
3. Wrong operand size
[rbx] loads 64 bits when used with mov rax. Use mov eax, [rbx] for 32-bit load.
4. Forgetting displacement sign
Displacement is signed. [rbx + -8] is valid but better written as [rbx - 8].
5. Absolute vs relative in 64-bit
Default is RIP-relative. Use [rel symbol] explicitly in 64-bit code.
Practice Questions
1. What are the components of an addressing mode? Base register, index register, scale factor (1, 2, 4, 8), and displacement.
2. How do you access array[4] of 8-byte elements?
mov rax, [array + 4*8] or with an index register: mov rcx, 4; mov rax, [array + rcx*8].
3. What does LEA do? Loads the effective address without accessing memory. Used for pointer arithmetic and fast arithmetic.
Challenge: Write assembly code that sums elements of a 64-bit integer array using indexed addressing.
FAQ
{{< faq question="Why is RIP-relative addressing default?" >} It enables position-independent code (PIC), essential for shared libraries and ASLR security. {{< /faq >}}
{{< faq question="Can I use two base registers?" >} No, the addressing mode allows only one base register. Use LEA to compute complex addresses first. {{< /faq >}}
{{< faq question="What is the displacement range?" >} Displacement can be 8-bit (-128 to 127) or 32-bit. The assembler chooses the smallest. {{< /faq >}}
{{< faq question="How do I access stack parameters?" >}
[rbp + 16] for first parameter, [rbp + 24] for second (after return address and saved RBP).
{{< /faq >}}
{{< faq question="Is there indirect addressing with scale?" >}
Yes: [rax*8] is valid when RAX holds a pointer (works as both base and index).
{{< /faq >}}
Mini Project
Implement array sum using indexed addressing:
section .data
array dq 10, 20, 30, 40, 50
length equ 5
section .text
global main
main:
xor rax, rax ; sum = 0
xor rcx, rcx ; index = 0
.loop:
add rax, [array + rcx*8] ; sum += array[index]
inc rcx
cmp rcx, length
jl .loop
ret
What's Next
Now that you understand addressing modes, explore stack operations and function calls.
| Topic | Description | Link |
|---|---|---|
| Assembly Stack | Stack operations | {{< ref "05-stack" >}} |
| Assembly Instructions | Instruction set | {{< ref "06-instructions" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro