4.2.4 Multiplying and Dividing Integers

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.

4.2.4.1 Using Multiplication Instructions

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.

4.2.4.2 Using Division Instructions

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.”