The Challenge of Integer Division

The Z80 CPU has no instruction for division. Every division operation must be performed using software algorithms based on repeated subtraction or shifting and subtraction (the same method used for manual long division).

Goal: Divide a 16-bit number (the Dividend) by an 8-bit number (the Divisor) to produce a 16-bit Quotient and an 8-bit Remainder.

The Algorithm: Binary Long Division

The most efficient method is to implement the Binary Long Division algorithm, which uses shifts and conditional subtraction.

The Principle: The routine loops 16 times (once for each bit of the dividend). In each loop:

  1. Shift the Dividend one bit left (into the Carry flag).
  2. Shift the Quotient one bit left (with the Carry flag filling the new low bit).
  3. Conditionally subtract the Divisor from the high part of the Dividend.

Z80 Implementation Focus

We’ll use dedicated registers for the operation:

Register Purpose
HL Dividend (Initially holds the number to be divided)
B Divisor (The number to divide by)
DE Quotient (The final result)
C Loop Counter (16 iterations)

Core Loop Logic (Simplified):

DIVIDE_16_BY_8:
    LD   C, 16              ; C ← Loop 16 times
    LD   DE, 0000H          ; DE ← Quotient (Starts at 0)
    
DIV_LOOP:
    ; 1. Shift Dividend Left (through Carry flag)
    ADD  HL, HL             ; Shift HL left (MSB goes into Carry)
    
    ; 2. Shift Quotient Left (Carry goes into Quotient's LSB)
    RL   E                  ; Rotate E left (Carry goes into bit 0)
    RL   D                  ; Rotate D left (Carry goes into bit 8)
    
    ; 3. Check if we can subtract Divisor
    LD   A, H               ; Check the high byte of the Dividend
    CP   B                  ; Compare H with Divisor (B)
    JP   C, NO_SUBTRACT     ; If Carry=1 (H < B), cannot subtract, skip

    ; Subtraction is possible: Subtract Divisor from High Byte of Dividend
    SUB  B                  ; A &larr; H - B
    LD   H, A               ; H &larr; Result of subtraction (H now updated)

NO_SUBTRACT:
    DJNZ DIV_LOOP           ; Loop 16 times

    ; The 16-bit Quotient is in DE. The 8-bit Remainder is in H.
    RET

Final Output

The final result of this process is:

  • The Quotient (the main result) is in the DE register pair.
  • The Remainder (the fractional part) is in the H register.