Skills101

Computer Organisation & Architecture (COA) · Lesson 4 of 8 · Updated ·

Instruction Sets and Addressing Modes — Formats, Immediate to Indexed Addressing, RISC vs CISC

An instruction set architecture (ISA) is the vocabulary a CPU understands: which operations exist, how they're encoded in bits, and how they find their operands. Addressing modes and instruction-format numericals are among the most asked COA questions in university and GATE exams.

1. Instruction format

An instruction is split into fields:

| opcode | mode | operand / address fields ... |
  • Opcode — which operation (ADD, LOAD, JUMP…). With k opcode bits you can have 2ᵏ distinct operations.
  • Operand fields — registers, memory addresses or constants.

Number of addresses per instruction (for X = A + B):

FormatExampleNotes
3-addressADD X, A, Bshort programs, long instructions
2-addressMOV X, A / ADD X, Bone operand is also the destination
1-address (accumulator)LOAD A / ADD B / STORE XACC is implied (like our toy CPU)
0-address (stack)PUSH A / PUSH B / ADD / POP Xoperands on a stack

2. Instruction format numericals

Example 1. A CPU has 64 registers and 32-bit instructions. An instruction has an opcode, two register operands and a 12-bit immediate. How many opcodes are possible?

Register field = log₂64 = 6 bits each → 12 bits; immediate 12 bits; opcode = 32 − 12 − 12 = 8 bits → 256 opcodes.

Example 2 (expanding opcodes). Instructions are 16 bits. Two-address instructions use a 4-bit opcode and two 6-bit address fields (4 + 6 + 6 = 16). There are 15 two-address instructions. What is the maximum number of one-address instructions?

A 4-bit opcode has 2⁴ = 16 patterns; 15 are used, so 1 pattern is free. A one-address instruction doesn't need the second 6-bit address field, so that free pattern can be extended with those 6 bits: 1 × 2⁶ = 64 one-address instructions.

import math

# Example 1
reg_bits = int(math.log2(64))
opcode_bits = 32 - 2 * reg_bits - 12
print("Ex1: opcode bits =", opcode_bits, "-> opcodes =", 2 ** opcode_bits)

# Example 2
two_addr_patterns = 2 ** 4
free_patterns = two_addr_patterns - 15
one_addr = free_patterns * 2 ** 6
print("Ex2: free 4-bit patterns:", free_patterns, "-> max one-address instructions:", one_addr)
Ex1: opcode bits = 8 -> opcodes = 256
Ex2: free 4-bit patterns: 1 -> max one-address instructions: 64

Rule: leftover opcode patterns × 2^(bits freed by dropping an address field).

3. Addressing modes

The effective address (EA) is the memory address where the operand actually is. Each mode is a different way to compute it.

Addressing modes compared: immediate (operand is in the instruction), direct (instruction holds the address), indirect (instruction holds the address of the address), register, register indirect, indexed or base plus offset, and PC-relative

ModeInstruction containsOperand isMemory accesses for operandUse
Immediatethe value itself#50constants
Direct (absolute)address AM[A]1global variables
Indirectaddress A of a pointerM[M[A]]2pointers
Registerregister RR0fastest; temporaries
Register indirectregister R holding an addressM[R]1pointers in registers
Indexed / base + offsetaddress A + index registerM[A + R]1arrays, struct fields
PC-relativeoffset dM[PC + d] (target PC+d for branches)1branches, position-independent code
Auto-incrementregister RM[R], then R ← R + size1stepping through arrays

4. Simulate the modes

memory = {100: 500, 200: 300, 300: 42, 500: 7, 510: 99}
R = {"R1": 300, "R2": 10}
PC = 150

def operand(mode, field):
    if mode == "immediate":         return field
    if mode == "direct":            return memory[field]
    if mode == "indirect":          return memory[memory[field]]
    if mode == "register":          return R[field]
    if mode == "register_indirect": return memory[R[field]]
    if mode == "indexed":           base, reg = field; return memory[base + R[reg]]
    if mode == "relative":          return memory[PC + field]

tests = [("immediate", 100), ("direct", 100), ("indirect", 100), ("register", "R1"),
         ("register_indirect", "R1"), ("indexed", (500, "R2")), ("relative", 50)]
for mode, field in tests:
    print(f"{mode:18} field={str(field):12} operand={operand(mode, field)}")
immediate          field=100          operand=100
direct             field=100          operand=500
indirect           field=100          operand=7
register           field=R1           operand=300
register_indirect  field=R1           operand=42
indexed            field=(500, 'R2')  operand=99
relative           field=50           operand=300

Trace two of them: indirect 100 → M[100] = 500 → M[500] = 7. Indexed (500, R2) → EA = 500 + 10 = 510 → M[510] = 99 (this is exactly arr[10] when the array starts at 500).

5. RISC vs CISC

RISC (Reduced Instruction Set)CISC (Complex Instruction Set)
Instructionsfew, simple, fixed lengthmany, complex, variable length
Memory accessonly LOAD/STORE touch memorymany instructions operate on memory directly
CPI~1 (easy to pipeline)varies, many cycles
Registersmanyfewer
Control unithardwiredoften microprogrammed
ExamplesARM (phones, Apple M-series), RISC-Vx86 (Intel/AMD PCs)

Modern x86 chips internally translate complex instructions into RISC-like micro-operations, so the line has blurred — but the exam distinctions above are still standard. RISC-V is an open ISA growing fast, including in Indian chip projects (e.g. the Shakti processors from IIT Madras).

6. Hardwired vs microprogrammed control

  • Hardwired control unit: control signals generated by fixed logic circuits — fast, hard to change (RISC).
  • Microprogrammed control unit: each instruction is a small program of micro-instructions stored in a control memory — flexible, easier to add complex instructions, slower (classic CISC).

Common mistakes

  • Immediate vs direct: #100 is the value 100; 100 (direct) is the value at address 100.
  • Counting memory accesses for indirect as 1 (it's 2 for the operand, plus the instruction fetch).
  • Forgetting that PC already points to the next instruction when computing PC-relative targets in exam questions (read the question's convention).

Quick recap

  • Instruction = opcode + operand fields; k opcode bits → 2ᵏ operations; expanding opcodes reuse leftover patterns.
  • Modes: immediate (value), direct M[A], indirect M[M[A]], register, register indirect M[R], indexed M[A+R], relative M[PC+d], auto-increment.
  • RISC: simple, fixed-length, load/store, pipelines well (ARM, RISC-V). CISC: complex, variable length (x86).
  • Hardwired control = fast; microprogrammed = flexible.

Practice what you learned

📝 Quiz: Instructions and Addressing Modes5 questions · instant answers & explanations · +10 XP · counts towards your free certificateTake the quiz →