1.2.4 - Immediate, direct, indirect and indexed addressing
An instruction's operand may be the data itself or information used to locate the data. You will distinguish four addressing modes, calculate effective addresses, and follow explicitly defined assembly notation without assuming every machine supports the same modes.
Distinguish a literal value from a memory address
An operand is the value or address information supplied with an instruction.
Addressing mode
An addressing mode specifies whether an instruction's operand supplies the data itself or information used to locate that data.
The same number can therefore cause different data to be loaded.
In immediate addressing, the operand contains the actual value to use. In direct addressing, the operand gives the address of a memory location containing the value. An effective address is the address from which the operand data will be read; an immediate operand needs no data-memory effective address because its value is already in the instruction.
For this lesson, generic assembly uses the following declared notation. LOAD copies the selected value into accumulator ACC. A number with # is immediate; brackets mean a memory read. This is teaching notation, not a claim that OCR LMC accepts these instructions.
LOAD #30 // ACC becomes the literal 30
LOAD [30] // ACC becomes the contents of memory address 30
If memory location 30 contains 72, the first instruction loads 30 and the second loads 72. The instruction itself must be fetched in both cases; immediate addressing avoids an additional operand-data memory read, not every memory access involved in executing the instruction.
| Mode | Given operand | Data selected | Operand-data memory reads in this model |
|---|---|---|---|
| Immediate | 30 | 30 | 0 |
| Direct | 30 | M[30] = 72 | 1 |
The instruction's defined addressing mode matters more than the appearance of a bare number. Native LDA 30 in LMC is direct: it loads mailbox 30, not the literal 30. Loading a constant in LMC normally uses a DAT mailbox followed by LDA.
Keep the operand, the effective address and the selected data separate. A number in source code is not automatically the literal value loaded.
Indirect addressing follows a stored address
In indirect addressing, the operand names a location containing another address. The processor reads this pointer value, then reads the data at the address it identifies. A pointer is an address value used to refer to another location; it is not automatically the final data.
Here double brackets explicitly mean two memory reads:
LOAD [[30]]
Suppose M[30]=72 and M[72]=9. The first read gets 72, so the effective address is 72. The second read gets 9, so ACC becomes 9. Direct LOAD [30] instead loads 72. The effective address and the loaded value must be reported separately when a trace asks for both.
Changing the pointer at address 30 to 80 redirects the same indirect instruction to M[80] without changing its source. This is useful when the required object or record can be in different places. It also introduces an extra operand-data read in this simplified memory model. An invalid pointer can address an unavailable location; indirect addressing does not itself validate that address.
We stop after the explicitly defined two reads. If M[72] happens to look like an address, that does not mean another read occurs: the mode specifies how far to follow the chain.
Indexed addressing adds an offset to a base address
In indexed addressing, an index register's value is added to the instruction's base address to form the effective address. The processor then reads the data there. In our declared notation, IX is the index register:
LOAD [100 + IX]
If IX=3, the effective address is 103. With M[103]=27, ACC becomes 27. Adding 3 to the stored value M[100] would be a different calculation: indexed addressing adds the offset to the address before reading the selected value.
Indexed addressing suits a sequence stored in adjacent locations. Suppose four one-mailbox readings occupy addresses 100, 101, 102 and 103. Setting IX to 0, 1, 2 and 3 lets the same base-100 instruction access each reading. If an element occupied two addressable units, offsets would need to advance by two; a question must state the element size or address convention. This lesson's examples use one unit per element and zero-based offsets.
The processor can calculate a requested address outside the intended array. With four readings, IX=4 selects address 104, which is not the fifth valid member of that four-element array. Bounds checking is a separate requirement, not a guaranteed property of indexed addressing.
Read and write assembly using an explicit mode contract
An assembly trace must combine the instruction's operation with the declared addressing mode. First interpret the operand, then obtain the selected data, then apply the operation. Never treat every address-looking number as a pointer or silently borrow syntax from another instruction set.
For the following original program, LOAD replaces ACC, ADD adds the selected value, and STORE [n] copies ACC to M[n]. IX begins at 2. M[50]=80, M[80]=7 and M[102]=11; other relevant values are supplied by the program.
LOAD #4
ADD [[50]]
ADD [100 + IX]
STORE [60]
The first step gives ACC=4. The indirect ADD reads M[50] to get effective address 80, then adds M[80]=7, giving 11. The indexed ADD reads effective address 102 and adds 11, giving 22. STORE writes 22 to M[60]. The pointer M[50] remains 80, and the reading M[102] remains 11.
To write a load of the third one-unit element in an array starting at 100, set IX=2 and write LOAD [100 + IX] under this contract. To read the data selected by pointer cell 50, use LOAD [[50]]. Neither can be expressed as a native OCR LMC instruction with this notation: LMC's listed ADD, SUB, LDA and STA use direct mailbox operands. Generic assembly or a simulator for a richer instruction set is the practical route for these other modes. For native LMC, constants can live in DAT cells; that still uses direct addressing.
For ungraded local writing practice, use a suitable assembly simulator whose manual explicitly supports the desired modes. Write a small load/add/store routine using each supported mode, document its syntax and element/address units, then inspect the effective address and fetched value when stepping. These generic examples are static textual assembly; NovaLearn Testing assesses their interpretation and reasoning here, rather than collecting an assembly source submission.