YouTip LogoYouTip

Assembly Addressing

Assembly Language – Addressing Modes |

\n\n

Addressing modes determine how the CPU locates the operands of an instructionβ€”where the data comes from and where the result is stored.

\n\n
\n\n

What Is an Addressing Mode

\n\n

The operand of each assembly instruction can be an immediate value, a value stored in a register, or data in memory.

\n\n

An addressing mode tells the CPU how to compute the actual address of an operand or directly specifies the operand value.

\n\n

The x86 architecture provides many flexible addressing modes. Understanding the use cases of each mode is the foundation for writing efficient assembly code.

\n\n
\n\n

Immediate Addressing

\n\n

The operand is directly embedded in the instruction as a constant value.

\n\n

When the source operand is an immediate value, the CPU reads it directly from the instruction stream, without accessing memory or registers.

\n\n

Examples

\n\n
; Immediate addressing examples\n\nmov eax,42      ; 42 is an immediate value, directly encoded in the instruction\nadd ebx,100     ; 100 is an immediate value\nmov ecx,0x2A    ; hexadecimal immediate value\nmov edx,'A'     ; character 'A' = 0x41, also an immediate value\n
\n\n
\n

Immediate addressing is the fastest "addressing mode" because the data resides within the instruction stream itselfβ€”the CPU obtains the data while fetching the instruction. However, immediate values can only be used as source operands, not destination operands. You cannot write mov 42, eax.

\n
\n\n
\n\n

Register Addressing

\n\n

The operand resides in a register, and the CPU operates directly on the register.

\n\n

This is also one of the fastest operations, as it avoids memory access overhead.

\n\n

Examples

\n\n
; Register addressing examples\n\nmov eax,ebx     ; copy value from ebx to eax (both operands use register addressing)\nadd ecx,edx     ; ecx = ecx + edx\npush eax        ; push value of eax onto the stack\ninc ebx         ; ebx = ebx + 1\n
\n\n
\n

Register addressing is the fastest. When writing assembly code, prioritize storing frequently accessed data in registers. However, registers are limited in number, so not all data can fit in them.

\n
\n\n
\n\n

Direct Addressing

\n\n

The operand is a memory address, directly specified in the instruction (typically using a variable label).

\n\n

The CPU must access memory once to read or write the data.

\n\n

Examples

\n\n
; File path: direct_addr.asm\n\n; Direct addressing examples\n\nsection .data\n value dd 12345678   ; define a double-word variable in memory\n name db 'tutorial',0\n\nsection .text\nglobal _start\n\n_start:\n; Direct addressing: read from memory\nmov eax,       ; read 4 bytes from memory address 'value' into eax\n; eax now contains 12345678\n\n; Direct addressing: write to memory\nmov dword ,98765   ; write 98765 to the memory location labeled 'value'\n\n; Direct addressing: read a byte\nmov al,           ; read first byte of 'name': 'r' = 0x72\nmov bl,[name + 1]       ; read second byte of 'name': 'u' = 0x75\n\nmov eax,1\nmov ebx,0\nint 0x80\n
\n\n
\n\n

Register Indirect Addressing

\n\n

The register contains a memory address, and the CPU uses that address to access memory.

\n\n

The register inside square brackets is treated as a pointer.

\n\n

Examples

\n\n
; File path: indirect_addr.asm\n\n; Register indirect addressing examples\n\nsection .data\n msg db 'Hello, TUTORIAL!',0xA\n len equ $ - msg\n\nsection .text\nglobal _start\n\n_start:\nmov eax, msg        ; place the address (pointer) of 'msg' into eax\nmov al,        ; indirect addressing: read the byte pointed to by eax\n; now al = 'H' = 0x48\n\n; Traverse the string and convert lowercase letters to uppercase\nmov esi, msg        ; esi points to the start of the string\nmov ecx, len        ; ecx holds the string length\n\nconvert_loop:\nmov al,        ; indirect addressing: read the character pointed to by esi\ncmp al,'a'          ; is it greater than or equal to 'a'?\njb next_char        ; if not, skip\ncmp al,'z'          ; is it less than or equal to 'z'?\nja next_char        ; if not, skip\nsub al,32           ; convert to uppercase (ASCII: lowercase - uppercase = 32)\nmov ,al        ; indirect addressing: write back to the location pointed to by esi\n\nnext_char:\ninc esi             ; move pointer to next character\nloop convert_loop   ; continue loop until all characters are processed\n\n; Output the converted string\nmov eax,4\nmov ebx,1\nmov ecx, msg\nmov edx, len\nint 0x80\n\nmov eax,1\nmov ebx,0\nint 0x80\n
\n\n
\n

Indirect addressing is the foundation for array traversal, string operations, and data structure access. ESI and EDI are specially designed registers tocombined with (combined with =combined with) indirect addressing; combined with inc esi, they make traversing contiguous memory effortless.

\n
\n\n
\n\n

Base Addressing

\n\n

Effective address = value of base register + displacement (offset).

\n\n

Base registers can include EBX, EBP, ESI, EDI, etc.

\n\n

Examples

\n\n
; Base addressing example: accessing struct members\n\nsection .data\n; Simulate a simple struct: {id, age, score}\n; id  = 2 bytes\n; age = 2 bytes\n; score = 4 bytes\n student db 0x01,0x00 ; id = 1\n         db 0x14,0x00 ; age = 20\n         dd 95        ; score = 95\n\nsection .text\nglobal _start\n\n_start:\nmov ebx, student      ; ebx holds the base address of the struct\n\n; Access members using base + offset\nmov ax,          ; read id (offset 0)\nmov ax,[ebx+2]        ; read age (offset 2)\nmov eax,[ebx+4]       ; read score (offset 4)\n\n; Modify age\nmov word [ebx+2],21   ; age = 21\n\n; Modify score\nmov dword [ebx+4],98  ; score = 98\n\nmov eax,1\nmov ebx,0\nint 0x80\n
\n\n
\n\n

Indexed Addressing

\n\n

Use an index register (ESI or EDI) plus a displacement to access array elements.

\n\n

Examples

\n\n
; Indexed addressing example: traversing an array\n\nsection .data\n array dd 10,20,30,40,50        ; array of 5 double-word elements\n array_len equ ($ - array)/4    ; number of elements = total bytes / 4\n\nsection .text\nglobal _start\n\n_start:\nmov ecx, array_len   ; loop counter\nmov esi,0            ; index (starting from 0)\nmov ebx,0            ; accumulator sum\n\nsum_loop:\nmov eax,[array + esi*4]   ; indexed addressing: array + index * element_size\n; esi * 4 because each element is 4 bytes\nadd ebx,eax               ; accumulate into ebx\ninc esi                   ; increment index\nloop sum_loop\n\n; ebx = 10+20+30+40+50 = 150\n\n; Indexed + displacement: access the second element\n; array + 2*4 = array + 8, i.e., 30\nmov eax,[array + 2*4]     ; eax = 30\n\nmov eax,1\nmov ebx,0\nint 0x80\n
\n\n
\n\n

Base-Indexed Addressing

\n\n

Effective address = base register + index register Γ— scale factor + displacement.

\n\n

This is the most powerful addressing mode in x86, enabling full address computation in a single instruction.

\n\n

Note: x86 supports only one index register multiplied by a scale factor; multiple registers with scale factors are not supported.

\n\n

Examples

\n\n
; Base-indexed addressing example: accessing a 2D array\n\nsection .data\n; 3 rows Γ— 4 columns 2D array\n matrix dd 1,2,3,4\n        dd 5,6,7,8\n        dd 9,10,11,12\n\nsection .text\nglobal _start\n\n_start:\n; Access matrix (2nd row, 3rd column; indices start at 0)\n; Address = matrix + row * bytes_per_row + column * bytes_per_element\n;         = matrix + 1*16 + 2*4\n;         = matrix + 24\nmov ebx, matrix       ; base register\nmov esi,24            ; precomputed total offset\n; Correct format: base + displacement\nmov eax,[ebx+esi]     ; eax = 7\n\n; Standard base-indexed format: [base + index*scale + displacement]\n; Directly access the 6th element (matrix = 7)\nmov edi,6\nmov eax,[matrix + edi*4]  ; eax = 7\n\n; Exit program\nmov eax,1\nmov ebx,0\nint 0x80\n
\n\n
\n\n

Overview of Addressing Modes

\n\n

The figure below fully illustrates the 7 addressing modes of x86 and how they work:

\n\n

Image 1: x86 Addressing Modes Overview

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Addressing ModeSyntax FormatEffective Address / ValueTypical Use Cases
Immediatemov eax, 4242 (constant value)Initialization, constant operations
Registermov eax, ebxValue of register ebxData transfer between registers
Directmov eax, Value at memory address varAccessing global variables
Indirectmov eax, Address = value of ebxPointer operations, memory traversal
Basemov eax, [ebx+8]Address = ebx + 8Accessing struct members
Indexedmov eax, [arr+esi*4]Address = arr + esi Γ— 4Accessing 1D arrays
Base-Indexedmov eax, [ebx+esi*4+8]Address = ebx + esi Γ— 4 + 82D arrays, complex structs
\n\n
\n

In 32-bit protected mode, all general-purpose registers can serve as base or index registers. This differs significantly from 16-bit real mode (where only BX, BP, SI, and DI can be used for addressing). The flexibility of 32-bit mode makes addressing much more convenient.

\n
← Assembly ConstantsAssembly Registers β†’