8086 Assembly Program for Multiplication of Two 8-bit Numbers

8-bit multiplication on the 8086 is simpler than its 16-bit counterpart in one important way: the result always fits in a single register pair. MUL with an 8-bit operand multiplies the implicit AL register by that operand and places the full 16-bit result in AX — no separate DX needed. 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 8086 Assembly Program to Multiply Two 16-bit Numbers for the 16-bit version first if needed.


The Problem: Multiplying 09h by 02h

We want to multiply 09h (9 decimal) by 02h (2 decimal) and store the result. Quick check: 9 × 2 = 18 = 12h. The debugger confirms AX=0012 ✓.

💡 Side note — 8-bit MUL always produces a 16-bit result in AX: When you write MUL src with an 8-bit operand, the 8086 computes AX = AL × src. The full 16-bit product lands in AX — AH holds the high byte, AL holds the low byte. The maximum possible product is FFh × FFh = FE01h, which fits in AX. No DX is involved for 8-bit multiplication.

Version 1 — MASM / TASM (Classic DOS Toolchain)

data segment
    a db 09h        ; 8-bit multiplicand
    b db 02h        ; 8-bit multiplier
    c dw ?          ; 16-bit result
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
    mov al, a       ; Load multiplicand into AL (09h)
    mul b           ; AX = AL * b  (AX = 09h * 02h = 0012h)

    mov c, ax       ; Store result in c

    int 3           ; Halt for debugging
code ends
end start
⚠️ Common mistake — loading BL then calling mul b: Some versions of this program load mov bl, b before calling mul b. The BL load is completely unused — mul b reads the multiplier directly from the memory variable b, not from BL. If you want to multiply by a register, write mul bl; if you want to multiply by a memory variable, write mul b. Mixing them (loading BL then calling mul b) just wastes a register load.


Step-by-Step Explanation

1. Data Segment

  • a db 09h: Stores the first operand (9 decimal) as an 8-bit value.
  • b db 02h: Stores the second operand (2 decimal) as an 8-bit value.
  • c dw ?: Reserves a 16-bit word for the result — wide enough to hold any 8-bit product.

2. Code Segment

  • mov ax, data / mov ds, ax: Initialize the data segment register.
  • mov ax, 0000h: Clear AX so AH=0 before loading AL.
  • mov al, a: Load the multiplicand (09h) into AL.
  • mul b: Multiply AL by the memory byte b. Result: AX = AL × b = 09h × 02h = 0012h.
  • mov c, ax: Store the 16-bit result in c.
  • int 3: Breakpoint interrupt — halts execution for debugging.

Flowchart

High-Level Overview

  1. Initialize DS and clear AX.
  2. Load multiplicand into AL.
  3. Execute MUL b: AX = AL × b.
  4. Store AX into result variable c.

Output

C:TASM>masm an8mul.asm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.
 
Object filename [an8mul.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:
 
  50402 + 450254 Bytes symbol space free
 
      0 Warning Errors
      0 Severe  Errors
 
C:TASM>link an8mul.obj
 
Microsoft (R) Overlay Linker  Version 3.60
Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.
 
Run File [AN8MUL.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment
 
C:TASM>debug an8mul.exe
-g
 
AX=0012  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  09 02 12 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-q

Confirm AX=0012: AH=00 (high byte, zero because the product fits in AL), AL=12h (18 decimal, the result). c is stored at offset 2 as 12 00 in little-endian ✔.


Understanding the Memory Dump

AddressHexDecimalExplanation
0B97:0000099Multiplicand a = 09h
0B97:0001022Multiplier b = 02h
0B97:000212 0018Result c = 0012h in little-endian (AL=12h, AH=00h)

Version 2 — emu8086 (Windows Emulator)

Tested with: emu8086 v4.08 on Windows 10.

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

org 100h

; --- Code ---
start:
    mov ax, 0000h   ; Clear AX
    mov al, a       ; Load multiplicand into AL (09h)
    mul b           ; AX = AL * b  (0012h)
    mov c, ax       ; Store result

    mov ax, 4c00h
    int 21h

; --- Data (after code to avoid execution as instructions) ---
a db 09h
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 Multiplication of Two 8-bit Numbers
; nasm -f bin an8mul.asm -o an8mul.com

bits 16
org  100h

start:
    xor ax, ax       ; Clear AX
    mov al, [a]      ; Load multiplicand into AL (09h)
    mul byte [b]     ; AX = AL * b  (0012h)
    mov [res], ax    ; Store result

    mov ax, 4c00h
    int 21h

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

Register State After Execution

RegisterValueMeaning
AL12Low byte of product: 09h × 02h = 12h (18 decimal)
AH00High byte — zero because product fits in 8 bits
AX0012Full 16-bit result
CF / OF0Clear because AH=0 (product fits in AL)

Frequently Asked Questions

Why is the result stored in the 16-bit AX when both operands are 8 bits?

Because the product of two 8-bit numbers can be up to 16 bits wide: FFh × FFh = FE01h. The 8086 always writes the full 16-bit product to AX so no precision is lost. In practice, when the result fits in 8 bits (AH=0), you can safely use only AL. When AH is non-zero, you need the full AX — which is why c is declared as dw.

What is the difference between mul b and mul bl?

mul b reads the multiplier from the memory address of variable b. mul bl reads the multiplier from the BL register. Both produce the same result here (since b = 02h and BL was loaded with the same value), but they are different instructions with different encodings. Using mul b is slightly more direct and avoids the need to load BL first.

What do CF and OF indicate after 8-bit MUL?

After 8-bit MUL, CF and OF are both 0 if AH=0 (the product fits entirely in AL). Both are 1 if AH is non-zero (the product overflows into AH). This lets you use JC or JO after MUL to detect whether the result fits in a single byte. Here, 09h × 02h = 12h — AH=0, so CF=OF=0.


Conclusion

8-bit multiplication on the 8086 multiplies AL by an 8-bit register or memory operand and places the 16-bit product in AX. The operand you supply to MUL is the multiplier — AL is always the implicit multiplicand. Declare the result variable as dw (not db) to handle products that overflow into AH.


See Also

3 thoughts on “8086 Assembly Program for Multiplication of Two 8-bit Numbers”

  1. Yes, Change ur career u are a failure. Children are suffering by learning 43 year old language and you are adding to that suffering.

    1. He helped as to pass off our clg lab sessions. I am a pro in C, but I cant do this becoz i started my programming carrier for embedded right from C.

Leave a Reply

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