3.2.3 Direct Memory Operands

A direct memory operand specifies the data at a given address. The address and size of the data are encoded into the internal representation of the instruction. However, the instruction acts on the contents of the address, not the address itself. You must usually specify the size of these operands so that the instruction knows how much memory to operate on.

The offset value of a direct memory operand is not resolved until link time, and the segment must always be in a segment register at run time. The assembler automatically handles address resolution.

You usually represent a direct memory operand in source code as a symbolic name previously declared with a data directive such as BYTE, as illustrated below:

.DATA? ; Segment for uninitialized data

var BYTE ? ; Reserve one byte at current address

; and assign this address to var

.CODE

.

.

.

mov var, al ; Load contents of byte register into

address specified by var

Any location in memory can be a direct memory operand as long as a size is specified and the location is fixed. The data at the address can change, but the address cannot. By default, instructions that use direct memory addressing use the DS register. You can create an expression that points to a memory location using any of the following operators:

Operator Name Symbol
Plus +
Minus
Index [ ]
Structure member .
Segment override :

These operators are discussed in more detail below.

Summary: Several operators can be used in expressions that evaluate to direct memory operands.

Plus and Minus

The result of combining a memory operand and a constant number with the plus or minus operator is a direct memory operand. However, the result of combining two memory operands with the minus operator is an immediate operand. For example:

memvar EQU array + 5 ; Address five bytes beyond array

immexp EQU mem1 - mem2 ; Distance between addresses

The second expression is legal only if both addresses are in the same segment.

The expression mem1 - mem2 is not relocatable, since the reference to the two labels represents a difference in addresses (offsets). The linker does not need to know about the labels in this statement.

Index

The index operator (brackets enclosing an index value) specifies the register or registers for indirect operands. It should contain a constant index when used with direct memory operands. It is equivalent to the plus operator. For example, the following statements are the same:

mov ax, array[5]

mov ax, array+5

Any direct memory operand can be enclosed in the index operator. The following are equivalent:

mov ax, var

mov ax, [var]

Some programmers prefer to enclose the operand in brackets to show that the contents, not the address, are used.

Structure Field

The structure operator (a period) accesses elements of a structure. A field within a structure variable can be accessed as a direct memory operand:

mov bx, structvar.field1

The address of the structure operand is the sum of the offsets of structvar and field1. See Section 5.2, “Structures and Unions,” for more information about structures.

Segment Override

The segment override operator (a colon) specifies a segment portion of the address that is different from the default segment. When used with instructions, this operator can apply to segment registers or segment names:

mov ax, es:farvar ; Use segment override

The assembler will not generate a segment override if the default segment is explicitly provided. Thus, the following two statements are equivalent:

mov [bx], ax

mov ds:[bx], ax

A segment name override or the segment override operator forces the operand to be an address expression.

mov WORD PTR FARSEG:0, ax ; Segment name override

mov WORD PTR es:100h, ax ; Legal and equivalent

mov WORD PTR es:[100h], ax ; expressions

; mov WORD PTR [100h], ax ; Illegal, not an address

As the example shows, a constant expression cannot be an address expression unless it has a segment override.