8086 Assembly Program for Division of Two 8-bit Numbers

8-bit division in 8086 assembly has a subtle but important difference from 16-bit division: the dividend is always the full 16-bit AX register, not just AL. When you write DIV b with a byte operand, the CPU divides the 16-bit value in AX by that byte — quotient lands in AL, remainder in AH. Getting AH cleared to zero before the divide is therefore essential for a correct result. This post walks through a working implementation in three environments: MASM/TASM, emu8086, and NASM.

Prerequisites: Familiarity with 8086 registers and the segment setup pattern. Read Understanding DW and DB in 8086 Assembly first if you are new to assembly.


The Problem: Dividing 28h by 02h

We want to divide 28h (40 decimal) by 02h (2 decimal) and store the result. Quick check: 40 ÷ 2 = 20 = 14h, remainder 0. The debugger confirms AX=0014 (AH=00 remainder, AL=14h quotient) ✓.

💡 Side note — 8-bit DIV divides AX, not just AL: For an 8-bit divisor, the 8086 treats the full 16-bit AX as the dividend — not just AL. Quotient → AL, Remainder → AH. This means if AH contains leftover garbage before the divide, the effective dividend is wrong. Always clear AH (with xor ah, ah or mov ah, 0) or zero the entire AX (with mov ax, 0) before loading AL with your dividend.

Version 1 — MASM / TASM (Classic DOS Toolchain)

data segment
    a db 28h        ; 8-bit dividend (40 decimal)
    b db 02h        ; 8-bit divisor (2 decimal)
    c dw ?          ; 16-bit result: AL=quotient, AH=remainder
data ends

code segment
assume cs:code, ds:data
start:
    mov ax, data    ; Load data segment address
    mov ds, ax      ; Initialize DS

    mov ax, 0000h   ; Clear AX entirely (AH=0 is critical for 8-bit DIV)
    mov al, a       ; Load dividend into AL (AX = 0028h)
    div b           ; AX / b: AL = quotient (14h), AH = remainder (00h)

    mov c, ax       ; Store quotient in AL, remainder in AH, both into c

    int 3           ; Halt for debugging
code ends
end start
⚠️ Common mistake — loading BL unnecessarily then using memory DIV: The original version of this program loads mov bl, b and then calls div b (a memory operand). The BL load is wasted — div b reads the divisor directly from memory, completely ignoring BL. Many students then change it to div bl thinking it is equivalent, but div bl uses the register while div b uses memory; both happen to hold 02h here, so the result is the same, but the code is cleaner without the unnecessary BL load.


Step-by-Step Explanation

1. Data Segment

  • a db 28h: Defines the 8-bit dividend (40 decimal).
  • b db 02h: Defines the 8-bit divisor (2 decimal).
  • c dw ?: Reserves a 16-bit word for the result. The quotient ends up in AL (low byte) and the remainder in AH (high byte), so storing all of AX into c captures both.

2. Code Segment

  • mov ax, 0000h: Clears the entire AX register. This is critical — AH must be 0 before loading AL, otherwise the 16-bit dividend in AX will be wrong.
  • mov al, a: Loads the dividend (28h) into AL. AX is now 0028h.
  • div b: Divides AX (0028h = 40 decimal) by the byte in memory variable b (02h). Quotient → AL = 14h (20 decimal), Remainder → AH = 00h.
  • mov c, ax: Stores AX into c. AL holds the quotient (14h), AH holds the remainder (00h).

Flowchart

Overall Process

  • Initialize registers and set up the data segment.
  • Clear AX, then load the dividend into AL (AX = 0028h).
  • Execute DIV b: AX ÷ b → AL (quotient), AH (remainder).
  • Store AX into result variable c and terminate.

Output

C:TASM>masm an8div.asm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.
 
Object filename [an8div.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:
 
  50402 + 450254 Bytes symbol space free
 
      0 Warning Errors
      0 Severe  Errors
 
C:TASM>link an8div.obj
 
Microsoft (R) Overlay Linker  Version 3.60
Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.
 
Run File [AN8DIV.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment
 
C:TASM>debug an8div.exe
-g
 
AX=0014  BX=0002  CX=002A  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B97  ES=0B87  SS=0B97  CS=0B98  IP=0019   NV UP EI PL NZ NA PO NC
0B98:0019 CC            INT     3
-d 0B97:0000
0B97:0000  28 02 14 00 00 00 00 00-00 00 00 00 00 00 00 00   (.............
-q


Understanding the Memory Dump

Memory AddressValue (Hex)DecimalExplanation
0B97:00002840Dividend a = 28h
0B97:0001022Divisor b = 02h
0B97:00021420Quotient in AL — result of 40 ÷ 2
0B97:0003000Remainder in AH — zero, exact division

Version 2 — emu8086 (Windows Emulator)

Tested with: emu8086 v4.08 on Windows 10.

; emu8086 version -- 8086 Assembly Program for Division of Two 8-bit Numbers
#make_COM#

org 100h

; --- Code ---
start:
    xor ax, ax      ; Clear AX (AH must be 0 before 8-bit DIV)
    mov al, a       ; Load dividend into AL (AX = 0028h)
    div b           ; AX / b -> AL = quotient (14h), AH = remainder (00h)
    mov c, ax       ; Store both quotient and remainder

    mov ax, 4c00h
    int 21h

; --- Data (after code to avoid execution as instructions) ---
a db 28h
b db 02h
c dw 0000h

Version 3 — NASM (Modern Open-Source Assembler)

Tested with: NASM 2.16.01, DOSBox 0.74-3.

; NASM version -- 8086 Assembly Program for Division of Two 8-bit Numbers
; nasm -f bin an8div.asm -o an8div.com

bits 16
org  100h

start:
    xor ax, ax       ; Clear AX (AH = 0 is mandatory before 8-bit DIV)
    mov al, [a]      ; Load dividend into AL (AX = 0028h)
    div byte [b]     ; AX / b -> AL = quotient (14h), AH = remainder (00h)
    mov [res], ax    ; Store result into variable res

    mov ax, 4c00h
    int 21h

; --- Data (after code to avoid execution as instructions) ---
a   db 28h
b   db 02h
res dw 0

Register State After Execution

RegisterValueMeaning
AL14Quotient: 28h ÷ 02h = 14h (20 decimal)
AH00Remainder: 40 ÷ 2 is exact, no remainder
AX0014AH:AL combined — quotient in low byte

Frequently Asked Questions

What exactly does 8-bit DIV divide?

When the operand of DIV is an 8-bit register or memory byte, the 8086 divides the full 16-bit value in AX by that byte. The quotient lands in AL and the remainder in AH. This is not the same as dividing AL by BL — AX is the dividend, not just AL.

How do I read back the remainder after the division?

After DIV b, AH contains the remainder. In this program mov c, ax stores the entire AX into the 16-bit variable c — so the low byte of c holds the quotient and the high byte holds the remainder. If you want them separately, store AL and AH into two different byte variables.

What is the maximum quotient for 8-bit division?

The quotient must fit in AL (0 to FFh = 0 to 255). If the quotient exceeds FFh — for example dividing AX=0300h by 02h gives a quotient of 180h which does not fit in AL — the CPU raises a Divide Overflow exception (INT 0) and the program crashes. Always ensure the quotient will be within 8-bit range before calling 8-bit DIV.


Conclusion

8-bit division on the 8086 divides the full 16-bit AX by an 8-bit operand, placing the quotient in AL and the remainder in AH. The most important habit is clearing AH before loading AL with the dividend — a dirty AH means a wrong dividend and a wrong result. The cleanest one-instruction way to do this is xor ax, ax before mov al, a.


See Also

7 thoughts on “8086 Assembly Program for Division of Two 8-bit Numbers”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.