4.2.1 Moving and Loading Integers

The primary instructions for moving integers from operand to operand and loading them into registers are MOV (Move), XCHG (Exchange), XLAT (Translate), CWD (Convert Word to Double), and CBW (Convert Byte to Word).

4.2.1.1 Moving Integers

The most common method of moving data, the MOV instruction, can be thought of as a copy instruction, since it always copies the source operand to the destination operand. Immediately after a MOV instruction, both the source and destination operands contain the same value.

The statements in the following example illustrate each type of memory move that can be performed with a single instruction. Note that you cannot move memory operands to memory operands in one operation.

; Immediate value moves

mov ax, 7 ; Immediate to register

mov mem, 7 ; Immediate to memory direct

mov mem[bx], 7 ; Immediate to memory indirect

; Register moves

mov mem, ax ; Register to memory direct

mov mem[bx], ax ; Register to memory indirect

mov ax, bx ; Register to register

mov ds, ax ; General register to segment

; register

; Direct memory moves

mov ax, mem ; Memory direct to register

mov ds, mem ; Memory to segment register

; Indirect memory moves

mov ax, mem[bx] ; Memory indirect to register

mov ds, mem[bx] ; Memory indirect to segment register

; Segment register moves

mov mem, ds ; Segment register to memory

mov mem[bx], ds ; Segment register to memory indirect

mov ax, ds ; Segment register to general

; register

This next example shows several common types of moves that require two instructions.

; Move immediate to segment register

mov ax, DGROUP ; Load immediate to general register

mov ds, ax ; Store general register to segment

; register

; Move memory to memory

mov ax, mem1 ; Load memory to general register

mov mem2, ax ; Store general register to memory

; Move segment register to segment register

mov ax, ds ; Load segment register to general

; register

mov es, ax ; Store general register to segment

; register

The MOVSX and MOVZX instructions for the 80386/486 processors extend and copy values in one step. See Section 4.2.1.4, “Extending Signed and Unsigned Integers.”

4.2.1.2 Exchanging Integers

The XCHG (Exchange) instruction exchanges the data in the source and destination operands. Data can be exchanged between registers or between registers and memory, but not from memory to memory:

xchg ax, bx ; Put AX in BX and BX in AX

xchg memory, ax ; Put "memory" in AX and AX in "memory"

; xchg mem1, mem2 ; Illegal- can't exchange between

; memory location

In some circumstances, register-to-register moves are faster with XCHG than with MOV. If speed is important in your programs, check the Reference to find the fastest clock speeds for various operand combinations allowed with MOV and XCHG.

4.2.1.3 Translating Integers from Tables

The XLAT (Translate) instruction loads data from a table into memory. The instruction is useful for translating bytes from one coding system to another. The syntax is

XLAT[[B]] [[[[segment:]]memory]]

Summary: XLAT and XLATB are synonyms.

The BX register must contain the address of the start of the table. By default, the DS register contains the segment of the table, but you can use a segment override to specify a different segment. Also, you need not give the operand except when specifying a segment override. (See Section 3.2.3, “Direct Memory Operands,” for information about the segment override operator.)

Before the XLAT instruction executes, the AL register should contain a value that points into the table (the start of the table is position 0). After the instruction executes, AL contains the table value pointed to. For example, if AL contains 7, the assembler puts the eighth byte of the table in the AL register.

This example, illustrating XLAT, looks up hexadecimal characters in a table to convert an eight-bit binary number to a string representing a hexadecimal number.

; Table of hexadecimal digits

hex BYTE "0123456789ABCDEF"

convert BYTE "You pressed the key with ASCII code "

key BYTE ?,?,"h",13,10,"$"

.CODE

.

.

.

mov ah, 8 ; Get a key in AL

int 21h ; Call DOS

mov bx, OFFSET hex ; Load table address

mov ah, al ; Save a copy in high byte

and al, 00001111y ; Mask out top character

xlat ; Translate

mov key[1], al ; Store the character

mov cl, 12 ; Load shift count

shr ax, cl ; Shift high character into

; position

xlat ; Translate

mov key, al ; Store the character

mov dx, OFFSET convert ; Load message

mov ah, 9 ; Display character

int 21h ; Call DOS

4.2.1.4 Extending Signed and Unsigned Integers

Since moving data to a different-sized register is illegal, you must “sign-extend” integers to convert signed data to a larger register or register pair.

Sign-extending means copying the sign bit of the unextended operand to all bits of the extended operand. The instructions in the following list sign-extend values as shown. They work only on signed values in the accumulator register.

Instruction Function

CBW Convert byte to word
CWD Convert word to doubleword
CWDE Convert word to doubleword extended (80386/486 only)
CDQ Convert doubleword to quadword (80386/486 only)

On the 80386/486, the CWDE instruction converts a signed 16-bit value in AX to a signed 32-bit value in EAX. The CDQ instruction converts a signed 32-bit value in EAX to a signed 64-bit value in the EDX:EAX register pair.

This example converts signed integers using CBW, CWD, CWDE, and CDQ.

.DATA

mem8 SBYTE -5

mem16 SWORD -5

mem32 SDWORD -5

.CODE

.

.

.

mov al, mem8 ; Load 8-bit -5 (FBh)

cbw ; Convert to 16-bit -5 (FFFBh) in AX

mov ax, mem16 ; Load 16-bit -5 (FFFBh)

cwd ; Convert to 32-bit -5 (FFFF:FFFBh)

; in DX:AX

mov ax, mem16 ; Load 16-bit -5 (FFFBh)

cwde ; Convert to 32-bit -5 (FFFFFFFBh)

; in EAX

mov eax, mem32 ; Load 32-bit -5 (FFFFFFFBh)

cdq ; Convert to 64-bit -5

; (FFFFFFFF:FFFFFFFBh) in EDX:EAX

Summary: Conversion instructions do not operate on unsigned numbers.

The procedure is different for unsigned values. Unsigned values are extended by filling the upper bits with zeros rather than by sign extension. Because the sign-extend instructions do not work on unsigned integers, you must set the value of the higher register to zero.

This example shows sign extension for unsigned numbers.

.DATA

mem8 BYTE 251

mem16 WORD 251

.CODE

.

.

.

mov al, mem8 ; Load 251 (FBh) from 8-bit memory

sub ah, ah ; Zero upper half (AH)

mov ax, mem16 ; Load 251 (FBh) from 16-bit memory

sub dx, dx ; Zero upper half (DX)

The 80386/486 processors provide instructions that move and extend a value to a larger data size in a single step. MOVSX moves a signed value into a register and sign-extends it. MOVZX moves an unsigned value into a register and zero-extends it.

; 80386/486 instructions

movzx dx, bl ; Load unsigned 8-bit value into

; 16-bit register and zero-extend

These special 80386 and 80486 instructions usually execute much faster than the equivalent 8086-80286 instructions.