Assembly Language β Addressing Modes |
\n\nAddressing 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\nThe operand of each assembly instruction can be an immediate value, a value stored in a register, or data in memory.
\n\nAn addressing mode tells the CPU how to compute the actual address of an operand or directly specifies the operand value.
\n\nThe 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\nThe operand is directly embedded in the instruction as a constant value.
\n\nWhen the source operand is an immediate value, the CPU reads it directly from the instruction stream, without accessing memory or registers.
\n\nExamples
\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\n\nImmediate 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
\nmov 42, eax.
\n\n
Register Addressing
\n\nThe operand resides in a register, and the CPU operates directly on the register.
\n\nThis is also one of the fastest operations, as it avoids memory access overhead.
\n\nExamples
\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\n\nRegister 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
Direct Addressing
\n\nThe operand is a memory address, directly specified in the instruction (typically using a variable label).
\n\nThe CPU must access memory once to read or write the data.
\n\nExamples
\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\nThe register contains a memory address, and the CPU uses that address to access memory.
\n\nThe register inside square brackets is treated as a pointer.
\n\nExamples
\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\n\nIndirect 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
\ninc esi, they make traversing contiguous memory effortless.
\n\n
Base Addressing
\n\nEffective address = value of base register + displacement (offset).
\n\nBase registers can include EBX, EBP, ESI, EDI, etc.
\n\nExamples
\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\nUse an index register (ESI or EDI) plus a displacement to access array elements.
\n\nExamples
\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\nEffective address = base register + index register Γ scale factor + displacement.
\n\nThis is the most powerful addressing mode in x86, enabling full address computation in a single instruction.
\n\nNote: x86 supports only one index register multiplied by a scale factor; multiple registers with scale factors are not supported.
\n\nExamples
\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\nThe figure below fully illustrates the 7 addressing modes of x86 and how they work:
\n\n| Addressing Mode | \nSyntax Format | \nEffective Address / Value | \nTypical Use Cases | \n
|---|---|---|---|
| Immediate | \nmov eax, 42 | \n 42 (constant value) | \nInitialization, constant operations | \n
| Register | \nmov eax, ebx | \n Value of register ebx | \n Data transfer between registers | \n
| Direct | \nmov eax, | \n Value at memory address var | \n Accessing global variables | \n
| Indirect | \nmov eax, | \n Address = value of ebx | \n Pointer operations, memory traversal | \n
| Base | \nmov eax, [ebx+8] | \n Address = ebx + 8 | \n Accessing struct members | \n
| Indexed | \nmov eax, [arr+esi*4] | \n Address = arr + esi Γ 4 | \n Accessing 1D arrays | \n
| Base-Indexed | \nmov eax, [ebx+esi*4+8] | \n Address = ebx + esi Γ 4 + 8 | \n 2D arrays, complex structs | \n
\nIn 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
YouTip