8086 Assembly Program to Multiply Two 16 bit Numbers

In this blog post, we will explore an 8086 assembly program designed to multiply two 16-bit numbers. The 8086 microprocessor, with its rich set of instructions and registers, makes it possible to perform arithmetic operations efficiently. This program demonstrates how to use the AX, BX, and DX registers to handle the multiplication process, ensuring accurate results for 16-bit operands. Let’s dive into the code and its detailed explanation!

data segment
a dw 1234h
b dw 5678h
c dd ?
data ends

code segment
assume ds:data, cs:code
start:
mov ax,data
mov ds,ax
mov ax,a
mov bx,b
mul bx
mov word ptr c,ax
mov word ptr c+2,dx
int 3
code ends
end start


“Writing an 8086 assembly program to multiply two 16-bit numbers is like teaching two toddlers to shake hands—they’ll get there eventually, but expect a lot of shifting and carrying along the way!”


Understanding the Code:

Data Segment

  • data segment: This defines the beginning of the data segment where variables are stored.
  • a dw 1234h: Defines a 16-bit (dw stands for “define word”) variable a initialized to 1234h (hexadecimal).
  • b dw 5678h: Defines another 16-bit variable b initialized to 5678h.
  • c dd ?: Defines a 32-bit (dd stands for “define doubleword”) variable c, which is uninitialized (? means no initial value).

Flowchart

Code Segment

  • code segment: This defines the beginning of the code segment where the instructions are stored.
  • assume ds:data, cs:code: Tells the assembler that the data segment register (ds) points to the data segment, and the code segment register (cs) points to the code segment.
  • start: This label marks the entry point of the program.
  • mov ax, data: Loads the starting address of the data segment into the ax register.
  • mov ds, ax: Transfers the address from ax to the ds register, effectively setting up the ds register to access the data segment.
  • mov ax, a: Loads the value of variable a (1234h) into the ax register.
  • mov bx, b: Loads the value of variable b (5678h) into the bx register.
  • mul bx: Multiplies the value in ax (from a) by the value in bx (from b). This is an unsigned multiplication.
    • The result of the multiplication is stored as a 32-bit value:
      • The lower 16 bits are stored in ax.
      • The upper 16 bits are stored in dx.
  • mov word ptr c, ax: Stores the lower 16 bits of the result (from ax) into the lower part of the c variable.
  • mov word ptr c+2, dx: Stores the upper 16 bits of the result (from dx) into the higher part of the c variable.
  • int 3: Generates a software interrupt (used here to indicate program termination or for debugging purposes).
  • code ends: Marks the end of the code segment.
  • end start: Indicates the program’s entry point to the assembler.

On High Level:

  1. The program initializes the data segment to access variables.
  2. It loads the 16-bit values of a and b.
  3. It multiplies these values, producing a 32-bit result.
  4. The result is stored in the variable c:
    • ax contains the lower 16 bits.
    • dx contains the upper 16 bits.

Output

C:\TASM>masm an16mul.asm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.

Object filename [an16mul.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:

  50326 + 450330 Bytes symbol space free

      0 Warning Errors
      0 Severe  Errors

C:\TASM>link an16mul.obj

Microsoft (R) Overlay Linker  Version 3.60
Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.

Run File [AN16MUL.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment

C:\TASM>debug an16mul.exe
-g

AX=0060  BX=5678  CX=0026  DX=0626  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B97  ES=0B87  SS=0B97  CS=0B98  IP=0015   OV UP EI PL NZ NA PO CY
0B98:0015 CC            INT     3
-d 0B97:0000
0B97:0000  34 12 78 56 60 00 26 06-00 00 00 00 00 00 00 00   4.xV`.&.........
0B97:0010  B8 97 0B 8E D8 A1 00 00-8B 1E 02 00 F7 E3 A3 04   ................
0B97:0020  00 89 16 06 00 CC 15 8A-86 70 FF 2A E4 50 B8 FD   .........p.*.P..
0B97:0030  05 50 FF 36 24 21 E8 77-63 83 C4 06 FF 36 24 21   .P.6$!.wc....6$!
0B97:0040  B8 0A 00 50 E8 47 5E 83-C4 04 5E 8B E5 5D C3 90   ...P.G^...^..]..
0B97:0050  55 8B EC 81 EC 84 00 C4-5E 04 26 80 7F 0A 00 74   U.......^.&....t
0B97:0060  3E 8B 46 08 8B 56 0A 89-46 FC 89 56 FE C4 5E FC   >.F..V..F..V..^.
0B97:0070  26 8A 47 0C 2A E4 40 50-8B C3 05 0C 00 52 50 E8   &.G.*[email protected].
-q

Understanding the Memory Dump

0B97:0000  34 12 78 56 60 00 26 06-00 00 00 00 00 00 00 00   4.xV`.&.........

This shows the memory contents starting at address 0B97:0000, which corresponds to the data segment. Let’s interpret the bytes:

  1. 34 12: The value of a (1234h in little-endian format).
  2. 78 56: The value of b (5678h in little-endian format).
  3. 60 00 26 06: The value of c (result of the multiplication), stored as a 32-bit number:
    • 60 00: Lower 16 bits of the result (AX).
    • 26 06: Upper 16 bits of the result (DX).
  4. 00 00 00 00 ...: Remaining memory space, currently unused or initialized to zero.

Multiplication Breakdown

The program multiplies a = 1234h and b = 5678h.

Unsigned Multiplication:

1234h×5678h=06266060h

  • Result (32-bit):
    • Lower 16 bits (AX): 0060h.
    • Upper 16 bits (DX): 0626h.

These values are stored in the c variable, as confirmed by the memory dump.

Leave a Reply

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