The 8086 family of processors uses different multiplication and division instructions for signed and unsigned integers. Multiplication and division instructions also have special requirements depending on the size of the operands and the processor the code runs on.
The MUL instruction multiplies unsigned numbers. IMUL multiplies signed numbers. For both instructions, one factor must be in the accumulator register (AL for 8-bit numbers, AX for 16-bit numbers, EAX for 32-bit numbers). The other factor can be in any single register or memory operand. The result overwrites the contents of the accumulator register.
Multiplying two 8-bit numbers produces a 16-bit result returned in AX. Multiplying two 16-bit operands yields a 32-bit result in DX:AX. The 80386/486 processor handles 64-bit products in the same way in the EDX:EAX pair.
This example illustrates multiplication of signed 16- and 32-bit integers.
.DATA
mem16 SWORD -30000
.CODE
.
.
.
; 8-bit signed multiply
mov al, 23 ; Load AL 23
mov bl, 24 ; Load BL * 24
mul bl ; Multiply BL -----
; Product in AX 552
; overflow and carry set
; 16-bit unsigned multiply
mov ax, 50 ; Load AX 50
; -30000
imul mem16 ; Multiply memory -----
; Product in DX:AX -1500000
; overflow and carry set
A nonzero number in the upper half of the result (AH for byte, DX or EDX for word) sets the overflow and carry flags.
On the 80186–80486 processors, the IMUL instruction supports three different operand combinations. The first syntax option allows for 16-bit multipliers producing a 16-bit product or 32-bit multipliers for 32-bit products on the 80386/486. The result overwrites the destination. The syntax for this operation is
IMUL register16, immediate
Summary: Multiplication by an immediate operand is possible on the 80386/486.
The second syntax option specifies three operands for IMUL. The first operand must be a 16-bit register operand, the second a 16-bit memory or register operand, and the third a 16-bit immediate operand. IMUL multiplies the memory (or register) and immediate operands and stores the product in the register operand with this syntax:
IMUL register16, memory16 | register16, immediate
For the 80386/486 only, a third option for IMUL allows an additional operand for multiplication of a register value by a register or memory value. This is the syntax:
IMUL register,{register| memory}
The destination can be any 16-bit or 32-bit register. The source must be the same size as the destination.
In all of these options, products too large to fit in 16 or 32 bits set the overflow and carry flags. The following examples show these three options for IMUL.
imul dx, 456 ; Multiply DX times 456 on 80186-80486
imul ax, [bx],6 ; Multiply the value pointed to by BX
; by 6 and put the result in AX
imul dx, ax ; Multiply DX times AX on 80386
imul ax, [bx] ; Multiply AX by the value pointed to
; by BX on 80386
The IMUL instruction with multiple operands can be used for either signed or unsigned multiplication, since the 16-bit product is the same in either case. To get a 32-bit result, you must use the single-operand version of MUL or IMUL.
The DIV instruction divides unsigned numbers, and IDIV divides signed numbers. Both return a quotient and a remainder.
Table 4.1 summarizes the division operations. The dividend is the number to be divided, and the divisor is the number to divide by. The quotient is the result. The divisor can be in any register or memory location except the registers where the quotient and remainder are returned.
Table 4.1 Division Operations
Size of Operand |
Dividend Register | Size of Divisor | Quotient |
Remainder |
16 bits | AX | 8 bits | AL | AH |
32 bits | DX:AX | 16 bits | AX | DX |
64 bits (80386 and 80486) | EDX:EAX | 32 bits | EAX | EDX |
Unsigned division does not require careful attention to flags. The following examples illustrate signed division, which can be more complex.
.DATA
mem16 SWORD -2000
mem32 SDWORD 500000
.CODE
.
.
.
; Divide 16-bit unsigned by 8-bit
mov ax, 700 ; Load dividend 700
mov bl, 36 ; Load divisor DIV 36
div bl ; Divide BL ------
; Quotient in AL 19
; Remainder in AH 16
; Divide 32-bit signed by 16-bit
mov ax, WORD PTR mem32[0] ; Load into DX:AX
mov dx, WORD PTR mem32[2] ; 500000
idiv mem16 ; DIV -2000
; Divide memory ------
; Quotient in AX -250
; Remainder in DX 0
; Divide 16-bit signed by 16-bit
mov ax, WORD PTR mem16 ; Load into AX -2000
cwd ; Extend to DX:AX
mov bx,-421 ; DIV -421
idiv bx ; Divide by BX -----
; Quotient in AX 4
; Remainder in DX -316
If the dividend and divisor are the same size, sign-extend or zero-extend the dividend so that it is the length expected by the division instruction. See Section 4.2.1.4, “Extending Signed and Unsigned Integers.”