Skip to main content

Command Palette

Search for a command to run...

Addressing Modes

Updated
•9 min read•View as Markdown
S
Computer Science student focused on systems programming, Linux, cybersecurity, and software development. I write technical articles and build projects to deepen my understanding of computer systems while documenting my learning journey.

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?

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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

  1. 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.

  1. 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.

  1. 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.

  1. 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.

Computer Organization & Architecture

Part 24 of 35

Explore the fundamental principles behind modern computers, from processor organization and memory systems to registers, buses, instruction execution, and architectural design. This series breaks down how computers are structured, how their components communicate, and how instructions are processed at the hardware level.

Up next

Implied Addressing Mode

In the previous article, we introduced addressing modes and learned that they describe how a CPU finds the operand required by an instruction. We'll now study each addressing mode individually, starti