PIC Microcontoller Math Method

Divide 16 bit int by 8 bit int to 8 bit int and remainder


#define bf_carry 3, 0
#define bf_zero 3, 2

#define same 1
#define wreg 0

#define stc bsf bf_carry
#define clc bcf bf_carry

;-[ Div ]--------------------------------------------------------------
;	call	w/: Number in f_divhi:f_divlo
; Returns: Quotient in f_divlo, remainder in f_divhi. W preserved.
;          Carry set if error. Z if divide by zero, NZ if divide overflow.
; Notes:   Works by left shifted subtraction.
;          Size = 29, Speed(w/ call&ret) = 7 cycles if div by zero
;          Speed = 94 minimum, 129 maximum cycles

Div;
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction. 
;    addlw 0          ; w+=0 (to test for div by zero)
	mov	Hack, W
	mov	W, #0	; w+=0 (to test for div by zero)
	add	W, Hack
    stc              ; set carry in case of error
	snb	bf_zero	; if zero
	ret	;   return (error C,Z)

	call	DivSkipHiShift
iDivRepeat = 8
while iDivRepeat

	call	DivCode

iDivRepeat--
endw

	rl	f_divlo	; C << lo << C

    ; If the first subtract didn't underflow, and the carry was shifted
    ; into the quotient, then it will be shifted back off the end by this
    ; last RLF. This will automatically raise carry to indicate an error.
    ; The divide will be accurate to quotients of 9-bits, but past that
    ; the quotient and remainder will be bogus and carry will be set.

	clrb	bf_zero	; NZ (in case of overflow error)
	ret	; we are done!

DivCode
	rl	f_divlo	; C << lo << C
	rl	f_divhi	; C << hi << C
	sb	bf_carry	; if Carry
	jmp	DivSkipHiShift	;
	sub	f_divhi, W	;   hi-=w
    stc                  ;   ignore carry
	ret	;   done
                         ; endif
DivSkipHiShift
	sub	f_divhi, W	; hi-=w
	snb	bf_carry	; if carry set
	ret	;   done
	add	f_divhi, W	; hi+=w
    clc                  ; clear carry
	ret	; done