Contents Up << >>

### Data Movement Instructions

The fundamental data movement operation is `MOV dest, source`, which copies a byte or a word from the source location to the destination. In general, either the source or the destination must be a register (you can't copy directly from one memory location to another with `MOV`); the only exception is that an immediate value may be moved straight to memory (however, there is no way to put an immediate value into a segment register in one operation). Here are the accepted forms:

            MOV     reg8, r/m/i8
            MOV     mem8, reg8
            MOV     mem8, BYTE imm8

            MOV     reg16, r/m/i16
            MOV     mem16, reg16
            MOV     mem16, WORD imm16

            MOV     r/m16, segreg
            MOV     segreg, r/m16

The CS segment register may not be used as a destination (you wouldn't want to do this anyway, since it would change where the next instruction comes from; to get this effect, you need to use a proper flow control instruction such as `JMP`).

To perform a swap of two locations instead of a one-way copy, there is also an exchange operation:

            XCHG    reg8, r/m8
            XCHG    reg16, r/m16

As a special case of this that does nothing except occupy space and take up processor time, the instruction to exchange the accumulator with itself (`XCHG AX, AX`) is given the special "no-operation'' mnemonic:

            NOP

For the special purpose of copying a far pointer (that is, a pointer that includes a segment address, so that it can refer to a location outside the current segment) from memory into registers, there are the `LDS` and `LES` instructions. Here are the accepted forms:

            LDS     reg16, mem32
            LES     reg16, mem32

For example, the instruction `LDS SI, [200h]` is equivalent to the pair of instructions `MOV SI, [200h]` and `MOV DS, [202h]`. The 8086 only supports loading the pointer into the DS or ES segment register.

An operation that is frequently useful when setting up pointers is to load the "effective address'' of a memory reference. That is, this instruction does the displacement plus base plus index calculation, but just stores the resulting address in the destination register, rather than actually fetching the data from the address. Here is the only form allowed on the 8086:

            LEA     reg16, mem

To push and pop data from the stack, the 8086 provides the following instructions. The top of stack is located at offset SP within the stack segment, so `PUSH AX`, for example, is equivalent to `SUB SP, 2` (recall that the stack grows downward) followed by `MOV [SS:SP], AX` (except that `[SS:SP]` isn't a valid form of memory reference).

            PUSH    r/m16
            PUSH    segreg

            POP     r/m16
            POP     segreg

As with `MOV`, you are not allowed to `POP` into the CS register (although you may `PUSH CS`).

Although they were not provided on the original 8086, the instructions to push and pop the FLAGS register (as mentioned earlier) are available in Virtual-8086 mode on the Pentium (they were actually introduced in the 80186):

            PUSHF
            POPF

Here are the other ways of reading or modifying the FLAGS register (apart from setting flags as the result of an arithmetic operation, or testing them with a conditional branch, of course). The Carry, Direction, and Interrupt Enable flags may be cleared and set:

            CLC
            CLD
            CLI
            STC
            STD
            STI

The Carry flag may also be complemented, or "toggled'' between 0 and 1:

            CMC

Finally, the bottom eight bits of the FLAGS register (containing the Carry, Parity, Auxiliary Carry, Zero, and Sign flags, as described above) may be transferred to and from the AH register:

            LAHF
            SAHF