PIC Microcontroller Math Method

Divide 24 bits by 16

Andrew David (akdavid at ultronics.co.uk), Software Manager, Ultronics Ltd, Cheltenham says:

This division routine uses the standard binary long-division algorithm. The loop iterates once for each bit in the numerator, so it goes round 24 times. For each loop the numerator (sorry, but I can never remember which is the dividend and the divisor - I guess the divisor is the denominator, but I'd hate to get it wrong) is left shifted 1 bit into the remainder, then the remainder is compared with the denominator. If the remainder is greater than the denominator, the denominator is subtracted from the remainder and a 1 is shifted into the quotient, otherwise a 0 is shifted into the quotient. If you can't see how the routine works, try running through an example on paper, in binary, then think about how you'd write the routine.
;=============================================================================
; DIV24_16u
;
;       Divides a 24bit number by a 16bit number. Unsigned.
;
;       Inputs: 
;		24-but numerator in ACCcLO:ACCdHI:ACCdLO
;		16-bit denominator in ACCbHI:ACCbLO
;
;       Outputs: 
;		24-bit quotient in ACCcLO:ACCdHI:ACCdLO
;		16-bit rem in ACCaHI:ACCaLO
;
;	Locals used:
;		R5Hi
;
;
; Inputs are not preserved.
; 
; No timing analysis performed.
; Andrew David, Software Manager, Ultronics Ltd, Cheltenham
; akdavid at ultronics.co.uk          http://www.ultronics.com
;
;=============================================================================

DIV24_16u:
        movlw   .24             ; for 24 shifts
        movwf   R5Hi            ;

        clrf    ACCaHI,f        ; clear remainder.
        clrf    ACCaLO,f        ;

d2416lp:rlcf    ACCdLO,f        ; build up remainder.
        rlcf    ACCdHI,f        ;
        rlcf    ACCcLO,f        ;
        rlcf    ACCaLO,f        ;
        rlcf    ACCaHI,f        ;

; remainder is 16-bit, but may have spilled over into carry.

        btfss   ALUSTA,C        ; check for remainder spill into carry.
        goto    d2416s          ;

        movfp   ACCbLO,WREG     ;
        subwfb  ACCaLO,f        ; Carry bit is the 17th bit of this
subtract!
        movfp   ACCbHI,WREG     ;
        subwfb  ACCaHI,f        ;
        bsf     ALUSTA,C        ; bit is known to be zero here.
        goto    d2416ns         ;

d2416s: movfp   ACCbLO,WREG     ; Compare remainder with divisor.
        subwf   ACCaLO,w        ;
        movfp   ACCbHI,WREG     ;
        subwfb  ACCaHI,w        ;
        btfss   ALUSTA,C        ;
        goto    d2416ns         ; (remainder < divisor), shift in a '0'
        movfp   ACCbLO,WREG     ; The remainder is larger, so subtract
the
        subwf   ACCaLO,f        ; ... divisor FROM the remainder and
        movfp   ACCbHI,WREG     ; ... shift a '1' into the quot.
        subwfb  ACCaHI,f        ;

d2416ns:decfsz  R5Hi,f          ; check all bits
        goto    d2416lp         ;
        rlcf    ACCdLO,f        ; shift in final quotient bit.
        rlcf    ACCdHI,f        ;
        rlcf    ACCcLO,f        ;

        return