8086 Addressing Modes page
mov
(move) instruction:
mov destination, sourceThis instruction copies the data from the source operand to the destination operand. The eight and 16 bit registers are certainly valid operands for this instruction. The only restriction is that both operands must be the same size. Now let's look at some actual 8086
mov
instructions:
mov ax, bx ;Copies the value from BX into AX mov dl, al ;Copies the value from AL into DL mov si, dx ;Copies the value from DX into SI mov sp, bp ;Copies the value from BP into SP mov dh, cl ;Copies the value from CL into DH mov ax, ax ;Yes, this is legal!Remember, the registers are the best place to keep often used variables. As you'll see a little later, instructions using the registers are shorter and faster than those that access memory. Throughout this chapter you'll see the abbreviated operands reg and r/m (register/memory) used wherever you may use one of the 8086's general purpose registers.
mov
instruction) allow you to specify one of the segment
registers as an operand. There are two restrictions on the use of the segment
registers with the mov
instruction. First of all, you may not
specify cs
as the destination operand, second, only one of
the operands can be a segment register. You cannot move data from one segment
register to another with a single mov
instruction. To copy
the value of cs
to ds
, you'd have to use some
sequence like:
mov ax, cs mov ds, axYou should never use the segment registers as data registers to hold arbitrary values. They should only contain segment addresses. But more on that, later. Throughout this text you'll see the abbreviated operand sreg used wherever segment register operands are allowed (or required).
mov al,ds:[8088h]
loads
the al
register with a copy of the byte at memory location
8088h. Likewise, the instruction mov ds:[1234h],dl
stores the
value in the dl
register to memory location 1234h:The displacement-only addressing mode is perfect for accessing simple
variables. Of course, you'd probably prefer using names like "I"
or "J" rather than "DS:[1234h]" or "DS:[8088h]".
Well, fear not, you'll soon see it's possible to do just that.
Intel named this the displacement-only addressing mode because a 16 bit
constant (displacement) follows the mov
opcode in memory. In
that respect it is quite similar to the direct addressing mode on the x86
processors (see the previous chapter). There are some minor differences,
however. First of all, a displacement is exactly that- some distance from
some other point. On the x86, a direct address can be thought of as a displacement
from address zero. On the 80x86 processors, this displacement is an offset
from the beginning of a segment (the data segment in this example). Don't
worry if this doesn't make a lot of sense right now. You'll get an opportunity
to study segments to your heart's content a little later in this chapter.
For now, you can think of the displacement-only addressing mode as a direct
addressing mode. The examples in this chapter will typically access bytes
in memory. Don't forget, however, that you can also access words on the
8086 processors :
By default, all displacement-only values provide offsets into the data
segment. If you want to provide an offset into a different segment, you
must use a segment override prefix before your address. For example, to
access location 1234h in the extra segment (es
) you would use
an instruction of the form mov ax,es:[1234h].
Likewise, to
access this location in the code segment you would use the instruction mov
ax, cs:[1234h].
The ds:
prefix in the previous examples
is not a segment override. The CPU uses the data segment register by default.
These specific examples require ds:
because of MASM's syntactical
limitations.
mov al, [bx] mov al, [bp] mov al, [si] mov al, [di]As with the x86
[bx]
addressing mode, these four addressing
modes reference the byte at the offset found in the bx, bp, si,
or di
register, respectively. The [bx], [si],
and [di]
modes use the ds
segment by default.
The [bp]
addressing mode uses the stack segment (ss
)
by default.mov al, cs:[bx] mov al, ds:[bp] mov al, ss:[si] mov al, es:[di]Intel refers to
[bx]
and [bp]
as base addressing
modes and bx
and bp
as base registers (in fact,
bp
stands for base pointer). Intel refers to the [si]
and [di]
addressing modes as indexed addressing modes
(si
stands for source index, di
stands for destination
index). However, these addressing modes are functionally equivalent. This
text will call these forms register indirect modes to be consistent.
Note: the [si]
and [di]
addressing modes work
exactly the same way, just substitute si
and di
for bx
above.
mov al, disp[bx] mov al, disp[bp] mov al, disp[si] mov al, disp[di]If
bx
contains 1000h, then the instruction mov cl,20h[bx]
will load cl
from memory location ds:1020h. Likewise,
if bp
contains 2020h, mov dh,1000h[bp]
will load
dh
from location ss:3020.bx, si,
and di
all use the data segment, the disp[bp]
addressing mode uses the stack segment by default. As with the register
indirect addressing modes, you can use the segment override prefixes to
specify a different segment:
mov al, ss:disp[bx] mov al, es:disp[bp] mov al, cs:disp[si] mov al, ss:disp[di]
You may substitute
si
or di
in the figure above
to obtain the [si+disp]
and [di+disp]
addressing
modes.bx
or bp
) and an index
register (si
or di
). The allowable forms for these
addressing modes are
mov al, [bx][si] mov al, [bx][di] mov al, [bp][si] mov al, [bp][di]Suppose that
bx
contains 1000h and si
contains
880h. Then the instruction
mov al,[bx][si]
would load al
from location DS:1880h. Likewise, if bp
contains 1598h and di
contains 1004, mov ax,[bp+di]
will
load the 16 bits in ax
from locations SS:259C and SS:259D.bp
use the data segment
by default. Those that have bp
as an operand use the stack
segment by default.You substitute di
in the figure above to obtain the
[bx+di]
addressing mode.
You substitute di
in the figure above for the [bp+di]
addressing mode.
mov al, disp[bx][si] mov al, disp[bx+di] mov al, [bp+si+disp] mov al, [bp][di][disp]You may substitute
di
in the figure above to produce the
[bx+di+disp]
addressing mode.You may substitute di
in the figure above to produce the
[bp+di+disp]
addressing mode.
Suppose bp
contains 1000h, bx
contains 2000h,
si
contains 120h, and di
contains 5. Then mov
al,10h[bx+si]
loads al
from address DS:2130; mov
ch,125h[bp+di]
loads ch
from location SS:112A; and
mov bx,cs:2[bx][di]
loads bx
from location CS:2007.
disp[bx], [bx][disp], [bx+disp], [disp][bx], and [disp+bx] [bx][si], [bx+si], [si][bx], and [si+bx] disp[bx][si], disp[bx+si], [disp+bx+si], [disp+bx][si], disp[si][bx], [disp+si][bx], [disp+si+bx], [si+disp+bx], [bx+disp+si], etc.MASM treats the "[ ]" symbols just like the "+" operator. This operator is commutative, just like the "+" operator. Of course, this discussion applies to all the 8086 addressing modes, not just those involving BX and SI. You may substitute any legal registers in the addressing modes above.
If you choose zero or one items from each of the columns and wind up with at least one item, you've got a valid 8086 memory addressing mode. Some examples:
disp
from column one, nothing from column two, [di]
from column 3, you get disp[di]
.
disp, [bx],
and [di]
. You get disp[bx][di]
.
[si]
. You get [si]
[bx]
, then choose [di]
.
You get [bx][di]
disp[dx][si]
is
illegal because you cannot obtain [dx]
from any of the columns
above.bx
contains 10h, the effective
address for 10h[bx]
is 20h. You will see the term effective
address in almost any discussion of the 8086's addressing mode. There is
even a special instruction load effective address (lea
) that
computes effective addresses.disp[bx][si]
is
more complex than [bx]
. See the instruction set reference in
the appendices for information regarding the cycle times of various addressing
modes on the different 80x86 processors.bx
contains 10h, then the instruction mov
al,0FFFFh[bx]
will load the al
register from location
ds:0Fh, not from location ds:1000Fh.