Multiplication and division use fixed registers: you name only one operand, the other is always the accumulator.
MUL: unsigned multiply
| Instruction | Multiplies | Result in |
|---|---|---|
MUL BL (a byte) | AL × BL | AX |
MUL BX (a word) | AX × BX | DX:AX (DX the high word, AX the low word) |
The result is twice as wide, so it always fits. CF and OF are 1 when the high half (AH, or DX) is needed.
DIV: unsigned divide
| Instruction | Divides | Quotient | Remainder |
|---|---|---|---|
DIV BL (a byte) | AX ÷ BL | AL | AH |
DIV BX (a word) | DX:AX ÷ BX | AX | DX |
Two ways DIV can stop the program with a divide overflow: dividing by 0, or a quotient too big for AL (or AX). Before DIV BX, set DX to 0 if your number is only in AX; a leftover value in DX makes the number huge.
; Read two digits and print their product (up to 81) with AAM.
.MODEL SMALL
.STACK 100H
.DATA
SAY DB 0DH, 0AH, 'Product: $'
.CODE
MAIN PROC
MOV AX, @DATA
MOV DS, AX
MOV AH, 1
INT 21H
SUB AL, '0'
MOV BL, AL ; the first digit
MOV AH, 1
INT 21H
SUB AL, '0' ; AL = the second digit
MUL BL ; AX = AL x BL
AAM ; AH = tens, AL = ones
MOV BX, AX ; keep them: INT 21h changes AH
LEA DX, SAY
MOV AH, 9
INT 21H
MOV DL, BH
ADD DL, '0'
MOV AH, 2
INT 21H ; the tens digit
MOV DL, BL
ADD DL, '0'
INT 21H ; the ones digit
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAINInput used: 78
AAM splits AL into its tens and ones (AH = AL ÷ 10, AL = AL mod 10): a quick way to print a number below 100.
Signed numbers
IMUL and IDIV are the same with signed numbers. Before IDIV, stretch the number to the double width with its sign: CBW turns AL into AX, CWD turns AX into DX:AX.
Printing any number
To print 2025, divide by 10 again and again: the remainders are the digits, last digit first (5, 2, 0, 2). Push each one, then pop them to print in the right order:
; Print a number in decimal: divide by 10, push each digit, pop and print.
.MODEL SMALL
.STACK 100H
.CODE
MAIN PROC
MOV AX, 2025 ; the number to print
MOV BX, 10
MOV CX, 0 ; how many digits
DIVIDE:
MOV DX, 0 ; DX:AX is the number
DIV BX ; AX = quotient, DX = the last digit
PUSH DX
INC CX
CMP AX, 0
JNE DIVIDE ; until nothing is left
PRINT:
POP DX ; the first digit comes off first
ADD DL, '0'
MOV AH, 2
INT 21H
LOOP PRINT
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAINCommon mistakes
- Forgetting
MOV DX, 0before a 16-bit DIV. - Expecting
MUL BLto put the answer in BL: it goes in AX. - Dividing a big number by a byte:
DIV BLwith AX = 1000 and BL = 2 gives 500, too big for AL, so it is a divide overflow. - Printing the remainders in the order they come out: they are the digits backwards.
Quick check
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.