3.1.2 Near and Far Addresses

Addresses which have an implied segment name or segment registers associated with them are called “near addresses.” Addresses which have an explicit segment associated with them are called “far addresses.” The assembler handles near and far code automatically, as described below. You must specify how to handle far data.

The Microsoft segment model puts all near data and the stack in a group called DGROUP. Near code is put in a segment called _TEXT. Each module's far code or far data is placed in a separate segment. This convention is described in Section 2.3.2, “Controlling the Segment Order.”

The assembler cannot determine the address for some program components, which are said to be relocatable. The assembler generates a fixup record and the linker provides the address once the location of all segments has been determined. Usually a relocatable operand references a label, but there are exceptions. Examples in the next two sections include information about the relocatability of near and far data.

Near Code

Control transfers within near code do not require changes to segment registers. The processor automatically handles changes to the offset in the IP register when control-flow instructions such as JMP, CALL, and RET are used. The statement

call nearproc ; Change code offset

changes the IP register to the new address but leaves the segment unchanged. When the procedure returns, the processor resets IP to the offset of the next instruction after the call.

Far Code

The processor automatically handles segment register changes when dealing with far code. The statement

call farproc ; Change code segment and offset

automatically moves the segment and offset of the farproc procedure to the CS and IP registers. When the procedure returns, the processor sets CS to the original code segment and sets IP to the offset of the next instruction after the call.

Near Data

Near data can usually be accessed directly. That is, a segment register already holds the correct segment for the data item. The term “near data” is often used to refer to the data in the DGROUP group.

After the first initialization of the DS and SS registers, these registers normally point into DGROUP. If you modify the contents of either of these registers during the execution of the program, the register may need to be reloaded prior to being used for addressing DGROUP data.

If a stack variable is accessed directly through BP or SP, the SS register is the default. Otherwise, the default is DS:

nearvar WORD 0

.

.

.

mov ax, nearvar ; Access near data through DS or SS

mov ax, [bp+6] ; Access near data through SS

In this example, nearvar is a relocatable label. The assembler does not know where the memory for nearvar will be allocated. The linker provides the address at link time. The expression [bp+6] is not relocatable. The linker does not need to provide an address for this expression.

Far Data

To read or modify a far address, a segment register must point to the segment of the data. This requires two steps. First load the segment (normally either ES or DS) with the correct value, and then (optionally) set an assume of the segment register to the segment of the address (or to NOTHING).

NOTE:

In flat model (OS/2 2.x), far addresses are rarely used. By default, all addressing is relative to the initial values of the segment registers. Thus, this section on far addressing does not apply to most flat model programs.

Summary: You can initialize ES.

One method commonly used to access far data is to initialize the ES segment register. This example shows two ways to do this:

; First method

mov ax, SEG farvar ; Load segment of the far address

mov es, ax

mov ax, es:farvar ; Provide an explicit segment

; override on the addressing

; Second method

mov ax, SEG farvar2 ; Load the segment of the

; far address

mov ex, ax

ASSUME ES:SEG farvar2 ; Tell the assembler that ES points

; to the segment containing farvar2

mov ax, farvar2 ; The assembler provides the ES

; override since it knows that

; the label is addressable

After loading the segment of the address into the ES segment register, you can either explicitly override the segment register so that the addressing is correct (method 1) or allow the assembler to insert the override for you (method 2). The assembler uses ASSUME statements to determine which segment register can be used to address a segment of memory. To use the segment override operator, the left operand must be a segment register, not a segment name. (See Section 3.2.3 for more information on segment overrides.)

If an instruction needs a segment override, the resulting code is slightly larger and slower, since the override must be encoded into the instruction. However, the resulting code may still be smaller than the code for multiple loads of the default segment register for the instruction.

The DS, SS, FS, and GS segment registers (FS and GS are available only on the 80386/486 processors) may also be used to provide for addressing through other segments.

If a program uses ES to access far data, it need not restore ES when finished (unless the program uses flat model). Some compilers require that you restore ES before returning to a module written in a high-level language.

Summary: You can reinitialize DS.

For a series of memory accesses to far data, you can reinitialize DS to the far data and then restore DS when you are finished. Use the ASSUME directive to let the assembler know that DS is no longer associated with the default data segment, as shown below:

push ds ; Save original segment

mov ax, SEG fararray ; Move segment into data register

mov ds, ax ; Initialize segment register

ASSUME ds:SEG fararray ; Tell assembler where data is

mov ax, fararray[0] ; Direct access faster

mov dx, fararray[2] ; (A relocatable expression)

.

.

.

pop ds ; Restore segment

ASSUME ds:@DATA ; and default assumption

The additional overhead of saving and restoring the DS register in this data access method may be worthwhile to avoid repeated segment overrides.

If a program changes DS to access far data, it should restore DS when finished. This allows procedures to assume that DS is the segment for near data. This is a convention used in many compilers, including Microsoft compilers.

Relocatable Data

The memory expression es:farvar is a relocatable memory expression, since the assembler cannot determine the address at assembly time.

Since no label is referenced, you may expect

mov ax, _myseg:0

to be nonrelocatable (in small model). However, in this case, _myseg:0 is a location in a local module whose memory location is dependent on the link order, so mov ax, _myseg:0 is relocatable.

A group name is also an immediate constant representing the beginning of the group. The first three expressions below are relocatable expressions; the fourth is not.

mov ax, DGROUP ; Relocatable

mov ax, @data ; Relocatable

mov ax, mygroup ; Relocatable

mov ax, ds:0 ; Not relocatable