8086 Assembly Program to Calculate the Factorial of an Integer Using Loops and Registers

In this post, we’ll walk through an 8086 assembly program that calculates the factorial of a given integer. This program highlights the power of the 8086’s loop instruction and the use of general-purpose registers for iterative calculations. We’ll use the AX register as an accumulator for the result and the CX register as a loop counter, which is its special-purpose function. Let’s get to the code!

data segment
    n   dw 5      ; The number to find the factorial of
    fact dw ?     ; To store the 16-bit result
data ends
 
code segment
    assume ds:data, cs:code
start:
    mov ax, data
    mov ds, ax
 
    mov cx, n     ; Load N (5) into the counter register CX
    mov ax, 1     ; Initialize factorial result (AX) to 1
 
fact_loop:
    mul cx        ; Multiply AX by CX. Result in DX:AX
    loop fact_loop ; Decrement CX, jump to fact_loop if CX != 0
 
    mov fact, ax  ; Store the final result from AX into 'fact'
 
    int 3         ; Halt execution (breakpoint for debugging)
code ends
end start

“Writing a factorial loop in 8086 assembly is like setting up a line of dominoes—you give the first one a push (initialize to 1), and the loop instruction just keeps knocking them down (multiplying) until CX runs out!”


Understanding the Code

Data Segment

  • data segment: Declares the area for storing variables.
  • n dw 5: Defines a 16-bit variable (dw for “define word”) named n and initializes it with the value 5. This is the number we’ll find the factorial of.
  • fact dw ?: Defines a 16-bit variable fact to store the final result. The ? means it’s uninitialized.

Flowchart

Code Segment

  • code segment: Declares the area for the program’s instructions.
  • assume ds:data, cs:code: Tells the assembler to link the DS register with our data segment and the CS register with our code segment.
  • start:: A label marking the program’s starting point.
  • mov ax, data / mov ds, ax: This two-step process initializes the Data Segment (DS) register. We must do this to access our variables (n and fact).
  • mov cx, n: Loads our number (5) from the variable n into the CX register. CX is used as the counter for the loop instruction.
  • mov ax, 1: Initializes the AX register to 1. AX will act as our accumulator, holding the factorial result as it’s calculated. This is the base case (0! = 1).
  • fact_loop:: A label marking the beginning of our loop.
  • mul cx: This is the core of our calculation. It multiplies the value in AX by the value in CX. The 8086 stores the 32-bit result across two registers: the upper 16 bits in DX and the lower 16 bits in AX. (For 5!, the result is 120, which fits in AX, so DX will be 0).
  • loop fact_loop: This powerful instruction does three things at once:
    1. It decrements CX by 1.
    2. It checks if CX is 0.
    3. If CX is not 0, it jumps back to the fact_loop label.
  • mov fact, ax: After the loop finishes (CX becomes 0), this instruction copies the final result from AX into our fact variable in the data segment.
  • int 3: This is a software interrupt used to stop the program, acting as a breakpoint for the debugger.

On High Level

  1. The program sets up the DS register to access its data.
  2. It initializes the counter CX with the number n (5).
  3. It initializes the result register AX to 1.
  4. It enters a loop that multiplies AX by CX, then decrements CX.
  5. This loop repeats until CX reaches 0.
  6. The final value in AX (the factorial) is stored in the fact variable.

Output

Here’s a sample session using MASM and DEBUG to assemble, link, and run the program.

C:\TASM>masm an1fact.asm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.
 
Object filename [an1fact.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:
 
   50326 + 450330 Bytes symbol space free
 
       0 Warning Errors
       0 Severe  Errors
 
C:\TASM>link an1fact.obj
 
Microsoft (R) Overlay Linker  Version 3.60
Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.
 
Run File [AN1FACT.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment
 
C:\TASM>debug an1fact.exe
-g
 
AX=0078  BX=0000  CX=0000  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B97  ES=0B87  SS=0B97  CS=0B98  IP=0012   OV UP EI PL NZ NA PO NC
0B98:0012 CC          INT     3
-d 0B97:0000
0B97:0000  05 00 78 00 00 00 00 00-00 00 00 00 00 00 00 00   ..x.............
0B97:0010  B8 97 0B 8E D8 8B 0E 00-00 B8 01 00 F7 E1 E2 FB   ................
0B97:0020  A3 02 00 CC 15 8A 86 70-FF 2A E4 50 B8 FD 05 50   .....p.*.P...P
...
-q

Understanding the Output

  • Register State (-g):
    • AX=0078: This is the final result. 78h (hexadecimal) is equal to 120 (decimal).
    • CX=0000: This shows the loop instruction completed successfully, as the counter has reached 0.
    • DX=0000: This confirms that the result (120) was small enough to fit in AX, and no overflow into DX occurred.
    • IP=0012: The instruction pointer is at the INT 3 instruction, right after storing the result.
  • Memory Dump (-d 0B97:0000):
    • 05 00: This is the variable n (5) stored in little-endian format.
    • 78 00: This is the variable fact (120 or 78h) stored in little-endian format, confirming the value from AX was saved correctly.

Factorial Breakdown

The program calculates 5! (5-factorial). Let’s trace the loop:

5! = 5 X 4 X 3 X 2 X 1 = 120

The loop executes as follows (values are shown before the mul instruction):

  1. Start: CX = 5, AX = 1
  2. mul cx -> $AX = 1 \times 5 = 5$. loop (CX becomes 4).
  3. Loop 2: CX = 4, AX = 5
  4. mul cx -> $AX = 5 \times 4 = 20$ (14h). loop (CX becomes 3).
  5. Loop 3: CX = 3, AX = 20
  6. mul cx -> $AX = 20 \times 3 = 60$ (3Ch). loop (CX becomes 2).
  7. Loop 4: CX = 2, AX = 60
  8. mul cx -> $AX = 60 \times 2 = 120$ (78h). loop (CX becomes 1).
  9. Loop 5: CX = 1, AX = 120
  10. mul cx -> $AX = 120 \times 1 = 120$ (78h). loop (CX becomes 0).
  11. End: CX is 0, the loop terminates.
  12. mov fact, ax stores 78h into the fact variable.

This confirms our program correctly calculated the factorial.

Leave a Reply

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