8086 Assembly Program to Compute the Power of a Number

This blog post details an 8086-assembly program that computes the power of a number, specifically baseexponent. This example demonstrates fundamental assembly concepts like loops, multiplication, and register manipulation to perform iterative arithmetic. Let’s get started!

data segment
    base dw 0003h
    exponent dw 0004h
    result dd ?
data ends

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

    ; Initialize result to 1 (R = B^0)
    mov word ptr result, 0001h
    mov word ptr result+2, 0000h

    ; Load base and exponent
    mov cx, exponent ; CX = exponent (loop counter)
    mov bx, base     ; BX = base

    cmp cx, 0000h
    je exit          ; If exponent is 0, result is already 1. Jump to exit.

power_loop:
    ; Multiply result by base
    ; The result is a 32-bit number in result[0] (lower word) and result[2] (upper word)
    ; Multiplication requires careful handling of the 32-bit result with a 16-bit multiplier.
    
    ; 1. Multiply the lower word of result by base
    mov ax, word ptr result ; AX = result[0]
    mul bx                  ; AX * BX -> DX:AX (32-bit product)
    push dx                 ; Save the higher word (DX) of the product
    mov word ptr result, ax ; Store the lower word (AX) of the product as the new result[0]

    ; 2. Multiply the upper word of result by base
    mov ax, word ptr result+2 ; AX = result[2]
    mul bx                    ; AX * BX -> DX:AX (32-bit product)
    
    ; 3. Add the two 16-bit 'carry' terms
    pop cx                    ; Retrieve the saved higher word (DX) from step 1 into CX
    add ax, cx                ; AX = AX + CX (Sum of two high words)
    adc dx, 0000h             ; DX = DX + 0 + Carry from the previous ADD (final carry from the 32-bit multiplication)
    
    ; 4. Store the final upper word
    mov word ptr result+2, ax ; Store AX as the new result[2]
    
    ; Handle the 32-bit overflow (DX is the final carry from the 32-bit multiplication)
    ; For a 32-bit result storage, this program assumes the result fits in 32-bits.
    ; If the power is large, overflow might occur, which is a limitation of this 32-bit storage approach.

    loop power_loop ; Decrement CX and jump back to power_loop if CX != 0

exit:
    int 3 ; Program termination
code ends
end start


Understanding the Code

This program is more complex than simple multiplication because it involves repeated 16-bit multiplication to compute a potentially 32-bit result, requiring special handling of carries and intermediate products.

Data Segment:

  • data segment: Defines the variables.
  • base dw 0003h: Declares a 16-bit word variable base, initialized to 310.
  • exponent dw 0004h: Declares a 16-bit word variable exponent, initialized to 410.
  • result dd ?: Declares a 32-bit doubleword variable result to store the final product, 34 = 8110 (0051h).

Flowchart:

Code Segment:

  • assume cs:code, ds:data: Directs the assembler on segment register usage.
  • start:: Program execution entry point.
  • mov ax, data / mov ds, ax: Segment Setup. Makes the data segment accessible.
  • mov word ptr result, 0001h / mov word ptr result+2, 0000h: Initialization. Sets the initial result (32-bit) to 1. (base0 = 1).
  • mov cx, exponent: Loads the exponent (4) into the CX register, which acts as the loop counter for the LOOP instruction.
  • mov bx, base: Loads the base (3) into the BX register, the multiplier.
  • cmp cx, 0000h / je exit: Checks if the exponent is 0. If so, the result is 1, and the program exits.
  • power_loop:: The label marking the start of the loop (where multiplication occurs).
    • 32-bit Multiplication Logic: The core of the program is the multiplication of the 32-bit result by the 16-bit base (in BX). The full calculation is:
    • (result[2] X 216 + result[0]) X base
    • = (result[2] X base) X 216 + (result[0] X base)
    • mov ax, word ptr result: Loads the lower word of the 32-bit result into AX.
    • mul bx: Multiplies AX X BX. The 32-bit product is stored in DX:AX.
    • push dx: Saves the upper word of this first product (which is a carry into the next 16-bit position) onto the stack.
    • mov word ptr result, ax: Stores the lower word (AX) of the product as the new result[0].
    • mov ax, word ptr result+2: Loads the upper word of the old 32-bit result into AX.
    • mul bx: Multiplies AX X BX. The 32-bit product is again stored in DX:AX. This product is (result[2] X base) X 216.
    • pop cx: Retrieves the saved carry (from result[0] X base) into CX.
    • add ax, cx: Adds the saved carry (in CX) to the current lower 16 bits of the upper product (in AX). This completes the calculation of the new upper word.
    • adc dx, 0000h: Adds DX (the carry from the multiplication in step 2) plus the Carry Flag (CF) set by the previous ADD. This final carry (in DX) would be the next higher word (the 5th byte) if we were storing a 48-bit result.
    • mov word ptr result+2, ax: Stores the new upper word (AX) as the new result[2].
  • loop power_loop: Decrements CX and jumps back to power_loop if CX != 0.
  • exit:: Label for program termination.
  • int 3: Halts the program.

On High-Level

  1. Initialization: Variables (base, exponent) are set, and the 32-bit result is initialized to 1.
  2. Segment Setup: The data segment is made accessible.
  3. Loop Setup: The exponent is loaded into the loop counter (CX).
  4. Loop/Multiplication: A loop executes exponent times:
    • The current 32-bit result is multiplied by the 16-bit base.
    • The multiplication is broken into two 16-bit parts, carefully managing the 32-bit product and the intermediate carries.
    • The new 32-bit product is stored back into result.
  5. Program Termination: Execution is halted.

Output

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

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

  50288 + 450368 Bytes symbol space free

      0 Warning Errors
      0 Severe  Errors

C:\TASM>link power.obj

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

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

C:\TASM>debug power.exe
-g

AX=0051 BX=0003 CX=0000 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B97 ES=0B87 SS=0B97 CS=0B98 IP=002F  NV UP EI PL NZ NA PO NC
0B98:002F CC              INT     3
-d 0B97:0000
0B97:0000  03 00 04 00 51 00 00 00-B8 97 0B 8E D8 C7 06 04  ....Q...........
0B97:0010  00 01 00 C7 06 06 00 00-00 8B CE 8B DB 83 F9 00  ................
0B97:0020  74 0D A1 04 00 F7 E3 52-A3 04 00 A1 06 00 F7 E3  t......R........
0B97:0030  59 03 C1 13 D2 A3 06 00-E2 EB CC E9 CD FF B8 0A  Y...............
0B97:0040  00 50 E8 47 5E 83 C4 04-5E 8B E5 5D C3 90 55 8B  .P.G^...^..]..U.
-q

Understanding the Memory Dump

This is the memory dump starting from address 0B97:0000, showing the contents of memory. Here is the breakdown:

0B97:0000  03 00 04 00 51 00 00 00-B8 97 0B 8E D8 C7 06 04  ....Q...........
  • The value 03 00 (stored as little-endian) represents base = 0003h.
  • The value 04 00 (stored as little-endian) represents exponent = 0004h.
  • After the program runs:
    • The value 51 00 00 00 represents the 32-bit result.
    • result holds 00000051h, which is the correct decimal result 34 = 8110 (51h).

Leave a Reply

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