Multiplication and division

Intermediate

Multiplication and division use fixed registers: you name only one operand, the other is always the accumulator.

MUL: unsigned multiply

InstructionMultipliesResult in
MUL BL (a byte)AL × BLAX
MUL BX (a word)AX × BXDX: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

InstructionDividesQuotientRemainder
DIV BL (a byte)AX ÷ BLALAH
DIV BX (a word)DX:AX ÷ BXAXDX

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 MAIN

Input used: 78

Open in compiler

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 MAIN
Open in compiler

Common mistakes

  • Forgetting MOV DX, 0 before a 16-bit DIV.
  • Expecting MUL BL to put the answer in BL: it goes in AX.
  • Dividing a big number by a byte: DIV BL with 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

1. AL = 6, BL = 7. After MUL BL, where is 42?
2. AX = 47, BL = 10. After DIV BL, what are AL and AH?
3. Why set DX to 0 before DIV BX?
4. When printing 2025 by dividing by 10, which digit comes out first?

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.