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