Addressing Modes
A CPU instruction tells the processor what operation to perform.
But when an instruction needs data, another question appears:
Where is that data located?
The method used by an instruction to specify the location of its operand is called an addressing mode.
Addressing modes are an important part of the Instruction Set Architecture (ISA) because they determine how the processor finds operands.
What Is an Addressing Mode?
An addressing mode is a method used by the CPU to determine where an instruction's operand is located.
For example, an instruction might need the value:
25
That value could be:
Inside the instruction itself
Inside a register
At a memory address
At a memory address stored in a register
At an address calculated using another register
Different addressing modes provide different ways to locate that operand.
Why Do We Need Different Addressing Modes?
Consider a program that needs to work with:
A single constant A register value An array A pointer A variable in memory A location relative to the current instruction
Using only one addressing method would make some operations inconvenient.
Addressing modes give the CPU flexibility.
They allow instructions to access data in different ways.
Operand and Effective Address
Before learning individual addressing modes, we need to understand two terms.
Operand
The operand is the data that an instruction operates on.
For example:
ADD R1, R2
The registers contain the operands.
Effective Address
The effective address (EA) is the actual memory address from which an operand is accessed, when memory addressing is involved.
For example:
LOAD R1, [1000]
If the instruction accesses memory location 1000, then:
EA = 1000
The exact meaning of the instruction syntax depends on the architecture.
Common Addressing Modes
The major addressing modes we'll study are:
Implied Addressing
Immediate Addressing
Register Addressing
Register Indirect Addressing
Auto-Increment Addressing
Auto-Decrement Addressing
Direct Addressing
Indirect Addressing
Relative Addressing
Base Register Addressing
Indexed Addressing
Each one answers the same basic question:
How does the CPU find the operand?
- Implied Addressing
In implied addressing, the operand is already implied by the instruction.
The instruction doesn't explicitly specify the operand.
For example:
CMA
could mean:
Accumulator ← NOT Accumulator
The accumulator is automatically understood.
No operand address needs to be written.
Example
Suppose:
AC = 1010
Instruction:
CMA
The CPU performs:
AC ← NOT AC
Result:
AC = 0101
The instruction itself tells the CPU which register is involved.
- Immediate Addressing
In immediate addressing, the actual operand value is included directly in the instruction.
For example:
MOV R1, #25
The value is:
25
The CPU doesn't need to look up the value in memory.
Conceptually:
R1 ← 25
Example
MOV R1, #10 ADD R1, #5
Conceptually:
R1 ← 10 R1 ← R1 + 5
Immediate addressing is useful when the program needs a constant value.
Important Point
In immediate addressing:
Operand = value inside instruction
Not:
Operand = memory address
For example:
#25
means the value 25.
- Register Addressing
In register addressing, the operand is stored in a CPU register.
For example:
ADD R1, R2
The processor gets the operand from R2.
Conceptually:
R1 ← R1 + R2
No main-memory lookup is required to obtain the register operand.
Example
Suppose:
R1 = 10 R2 = 5
After:
ADD R1, R2
we get:
R1 = 15
Register addressing is generally very fast because registers are inside the CPU.
- Register Indirect Addressing
This one is slightly different.
The register doesn't contain the actual data.
Instead, the register contains a memory address where the data is stored.
For example:
R1 = 1000
and:
Memory[1000] = 25
If an instruction uses register indirect addressing:
LOAD R2, [R1]
the CPU interprets it conceptually as:
R2 ← Memory[R1]
Therefore:
R2 ← Memory[1000] R2 ← 25
The Key Difference
Register Addressing
R1 = 25
Operand = 25
Register Indirect
R1 = 1000 Memory[1000] = 25
Operand = Memory[1000]
So:
Register addressing → Register contains the data
Register indirect → Register contains the address of the data
This concept is extremely important when you later study pointers in C and assembly language.
- Auto-Increment Addressing
In auto-increment addressing, a register contains the address of an operand.
After accessing the operand, the register is automatically increased.
Conceptually:
Operand ← Memory[R1]
R1 ← R1 + d
where d depends on the size of the data being accessed.
For example:
R1 = 1000 Memory[1000] = 25
After accessing the operand:
Operand = 25
and:
R1
automatically moves to the next appropriate address.
Why Is This Useful?
Auto-increment addressing is particularly useful when processing consecutive memory locations.
For example, when reading an array:
Array[0] Array[1] Array[2] Array[3]
The processor can access one element and automatically advance the pointer.
- Auto-Decrement Addressing
Auto-decrement addressing works similarly, except the register is automatically decreased.
Conceptually:
R1 ← R1 - d
Operand ← Memory[R1]
The exact order can vary depending on the architecture.
This addressing mode can be useful when moving backward through a sequence of memory locations or when working with stack-related operations.
- Direct Addressing
In direct addressing, the instruction contains the memory address of the operand.
For example:
LOAD R1, 1000
Conceptually:
R1 ← Memory[1000]
If:
Memory[1000] = 50
then:
R1 = 50
The address is directly specified by the instruction.
Direct Addressing
Instruction │ │ contains address 1000 ▼ Memory[1000] │ ▼ Operand
Therefore:
EA = Address field
- Indirect Addressing
In indirect addressing, the address field doesn't directly identify the final operand.
Instead, it identifies a memory location that contains the actual address.
For example:
Instruction address field = 1000
and:
Memory[1000] = 2000 Memory[2000] = 50
The CPU performs:
1000 → 2000 → 50
So:
EA = Memory[1000] EA = 2000
Then:
Operand = Memory[2000] Operand = 50
Direct vs Indirect
This distinction is extremely important.
Direct
Instruction │ ▼ Address 1000 │ ▼ Memory[1000] │ ▼ Operand
Indirect
Instruction │ ▼ Address 1000 │ ▼ Memory[1000] │ ▼ Address 2000 │ ▼ Memory[2000] │ ▼ Operand
Indirect addressing therefore requires an additional level of address lookup.
- Relative Addressing
In relative addressing, the effective address is calculated using the current instruction location and an offset.
A simplified formula is:
EA = PC + Offset
where:
PC = Program Counter
Offset = value contained in the instruction
For example:
PC = 1000 Offset = 20
Then:
EA = 1000 + 20 EA = 1020
Why Use Relative Addressing?
Relative addressing is useful for things such as:
Branch instructions
Loops
Position-independent code
Nearby data
For example, a conditional branch might say conceptually:
PC ← PC + Offset
instead of storing a complete absolute address.
- Base Register Addressing
In base register addressing, the effective address is calculated by adding a displacement to a base register.
The basic formula is:
EA = Base Register + Displacement
For example:
Base Register = 5000 Displacement = 100
Then:
EA = 5000 + 100 EA = 5100
The processor accesses the operand at that effective address.
Why Use a Base Register?
Base registers are useful when working with:
Data structures
Memory regions
Relocatable programs
Arrays and records
Operating-system memory management concepts
The base register provides a starting point, while the displacement identifies a location relative to it.
- Indexed Addressing
In indexed addressing, an index register is combined with an address or base value to calculate the effective address.
A simplified formula is:
EA = Address + Index Register
For example:
Address = 1000 Index Register = 20
Then:
EA = 1000 + 20 EA = 1020
The CPU accesses the operand at address 1020.
Indexed Addressing and Arrays
Indexed addressing is especially useful for accessing elements of arrays.
Imagine:
Array: 1000 → A 1004 → B 1008 → C 1012 → D
If the processor can calculate addresses using an index, it can move through the array systematically.
For example:
Base address + Index
becomes:
1000 + 0 1000 + 4 1000 + 8 1000 + 12
The exact calculation depends on the processor and data size.
Base Register vs Indexed Addressing
These two modes are similar, but their typical purposes differ.
Base Register
EA = Base + Displacement
The base register usually identifies a starting memory region.
Indexed
EA = Address/Base + Index
The index is commonly used to move through elements or positions.
In real processors, architectures can provide more flexible combinations than these simplified formulas suggest.
Comparing the Addressing Modes
Addressing Mode
Where is the operand/address?
Implied
Implied by instruction
Immediate
Inside instruction
Register
In a register
Register Indirect
Register contains memory address
Auto-Increment
Register contains address, then automatically increments
Auto-Decrement
Register is automatically decremented
Direct
Address is directly in instruction
Indirect
Instruction points to an address containing another address
Relative
PC + offset
Base Register
Base register + displacement
Indexed
Address/base + index
A Simple Way to Remember Them
Think of the question:
"Where do I get the operand?"
Implied
You already know where it is.
Immediate
The value is right here.
Register
The value is in this register.
Register Indirect
This register tells me where the value is.
Direct
The instruction gives me the memory address.
Indirect
The instruction gives me an address that leads to another address.
Relative
Start from the PC and move by an offset.
Base Register
Start from a base and add a displacement.
Indexed
Start from a location and add an index.
Why Addressing Modes Matter
Addressing modes aren't just theoretical concepts.
They are fundamental to:
Assembly language
Compilers
Pointers
Arrays
Loops
Function calls
Operating systems
Embedded systems
CPU instruction sets
When you eventually write assembly, you'll see these ideas directly in real instructions.
Final Thoughts
An instruction tells the CPU what to do, while the addressing mode helps the CPU determine where the required operand comes from.
The same operation can therefore access data in very different ways.
For example:
Immediate → value is in instruction
Register → value is in register
Register Indirect → register contains address
Direct → instruction contains address
Indirect → address points to another address
Relative → PC + offset
Base → base + displacement
Indexed → address/base + index
Understanding addressing modes is one of the most important steps before moving into assembly language.
Next, we'll start examining these modes individually, beginning with the simplest ones.
Next: Implied Addressing Mode.
