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:
mov W, #24 ; for 24 shifts
mov R5Hi, W ;
clr ACCaHI ; clear remainder.
clr ACCaLO ;
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.
sb ALUSTA.C ; check for remainder spill into carry.
jmp d2416s ;
movfp ACCbLO,WREG ;
subwfb ACCaLO,f ; Carry bit is the 17th bit of this
subtract!
movfp ACCbHI,WREG ;
subwfb ACCaHI,f ;
setb ALUSTA.C ; bit is known to be zero here.
jmp d2416ns ;
d2416s: movfp ACCbLO,WREG ; Compare remainder with divisor.
mov W, ACCaLO-w ;
movfp ACCbHI,WREG ;
subwfb ACCaHI,w ;
sb ALUSTA.C ;
jmp d2416ns ; (remainder < divisor), shift in a '0'
movfp ACCbLO,WREG ; The remainder is larger, so subtract
the
sub ACCaLO, W ; ... divisor FROM the remainder and
movfp ACCbHI,WREG ; ... shift a '1' into the quot.
subwfb ACCaHI,f ;
d2416ns:decfsz R5Hi,f ; check all bits
jmp d2416lp ;
rlcf ACCdLO,f ; shift in final quotient bit.
rlcf ACCdHI,f ;
rlcf ACCcLO,f ;
ret