Immediate and Direct Addressing

Defining the Modes

The two most basic addressing modes are called "immediate" and "direct."

Immediate Addressing
In immediate addressing, the instruction itself contains the value to be used. This is like using a constant like 7 or 39 in an expression in a higher level language.

Direct Addressing
In direct addressing, the instruction tells where the value can be found, but the value itself is out in memory. In a high level language, direct addressing is frequently used for things like global variables.

Examples in High Level Languages

Suppose we have a statement in C like

i = j + 3;

i and j are variables, so they are out in memory. To execute this statement, we will need to fetch j from memory, and write our result to i. That means the instructions we generate need to have the addresses of i and j, and needs to read and write those addresses as appropriate.

The number 3, on the other hand, is an actual value appearing in the statement. So, our code needs to include 3 itself.

Even if we define a symbol, like

#define FRED 3
i = j + FRED;

FRED gets replaced by 3, and immediate addressing still ends up being used.

Translating to Assembly Code

In assembly code, the statement described there takes three steps:

  1. Fetch j from memory.
  2. Add the constant 3 to it.
  3. Put the result into memory at i

In assembly code, this becomes:

ldaa j
adda #3
staa i

Specifying Direct and Immediate Mode in Assembly Code

In a high level language, we don't (ordinarily) specify addressing modes. Instead, we just use variables and constants and rely on the language to know what we're talking about: if we use the constant 3, the compiler generates immediate mode; if we use the variable j the compiler generates direct mode.

The assembler doesn't work that way. At this level, the assembler is perfectly happy to use a constant 1 as a direct address, or to use the address of j as an immediate value. So we have to tell the assembler what we want to do.

We do this by putting a # immediately in front of the operand for immediate addressing, and leaving it off for direct addressing. If we forget the #, the assembler will be perfectly happy; it's not an error. But it's likely to be a bug!

Extended Addressing

Many small computers (including the HC11) actually have to forms of direct addressing, so we can handle small addresses more efficiently than large addresses. In the HC11, an address between $0000 and $00ff can be represented as eight bits, while addresses from $0100 through $ffff require 16. Eight bit addresses are called "direct," while 16 bit addresses are called "extended."

We don't have to worry about direct vs. extended addresses. If it's possible to use a direct address (the instruction has a direct form, and the address will fit in eight bits) the assembler will generate a direct address; otherwise, it will generate an extended address.

Reserving Space for Variables

It would be possible to define variables in assembly code completely "by hand." We could have code that said something like

i equ 0
j equ 1

Which would set i at address 000016 and j at address 000116. While that will work, it's inconvenient and easy to make errors. It's problematic enough for scalar variables; when we get to arrays it'll be really bad.

So, instead, we have a way to reserve space for variables (this is analogous to declaring variables in a high level language). We do this with the rmb directive. If we say

    org    RAM
i   rmb    1
j   rmb    1

The assembler will:

  1. Start working at address RAM (which we should have defined as 0 with equ)
  2. Reserve one byte of space for i. Since the assembler is working at location 0, i will be at 000016
  3. Reserve one byte of space for j. Since we just reserved a byte at 000016, this byte will be at 000116.

Here's what this looks like in an assembly listing file:

  Assembling vars.asm
0001 0000                         RAM     equ   0
0002 0000                                 org   RAM
0003 0000                         i       rmb   1
0004 0001                         j       rmb   1

Notice that the second column is telling us where we're putting i and j

Last modified: Fri Feb 6 09:56:49 MST 2004