; ; *************************************************************************** ; *** Bubble Software Parallax to PIC Source Converter. Copyright 1999. *** ; *** http://www.picnpoke.com email: sales@picnpoke.com *** ; *************************************************************************** ; ; DIVIDE ; Divide one 16-bit number into another, returning the 16-bit result and ; the remainder. Upon entry, the top of the division fraction (the dividend) ; must be in topH and topL, and the bottom (divisor) in btmH and btmL. ; If division by zero is attempted, the routine will return immediately with ; the error code of 0FFh in w. Otherwise, it will perform the division, leaving ; the remainder in topH and topL and the result (quotient) in qH and qL. ; Upon return from a successful division, w contains 0. ; Device data and reset vector P = pic16c55 #include <16c55.inc> ; processor assembler definitions _CONFIG _xt_osc & _wdt_off & _protect_off reset start org 8 topH Res d'1' ; MSB of top of fraction. topL Res d'1' ; LSB of top of fraction. btmH Res d'1' ; MSB of bottom of fraction. btmL Res d'1' ; LSB of bottom of fraction. qH Res d'1' ; MSB of quotient. qL Res d'1' ; LSB of quotient. count Res d'1' ; temporary counter index Res d'1' ; temporary counter org 0 start MOVLW d'0' ; Set to outputs to display TRIS 6h MOVLW d'0' ; results on LEDs. TRIS 7h MOVLW 0x33 ; Problem: divide MOVWF topH MOVLW 0x0A ; 330Ah by 00A3h. MOVWF topL MOVLW 0x00 MOVWF btmH MOVLW 0x00A3 MOVWF btmL CALL divide MOVF qL,w ; Display quotient in binary MOVWF 6h MOVF qH,w ; on LEDs connected to rb and rc. MOVWF 7h GOTO $ ; Endless loop Divide MOVF btmH,w ; Check for division by 0. IORWF btmL,w BTFSC status,z RETLW d'255' ; Error code= 255: return. MOVLW d'1' ; Otherwise, initialize variables MOVWF count CLRF index ; for the division. CLRF qH CLRF qL Divide_sh_loop BTFSC btmH,d'7' ; Shift divisor left GOTO Divide_d1 BCF status,c ; until msb is in RLF btmL ; btmH.7. RLF btmH ; count = no. of shifts+1. INCF count GOTO Divide_sh_loop Divide_d1 BCF status,c RLF qL ; Shift quotient left. RLF qH MOVF btmL,w ; top = top - btm. SUBWF topL BTFSC status,c ; If top - btm < 0 then GOTO Divide_d2 MOVLW d'1' ; top = top + btm SUBWF topH BTFSC status,c ; The idea is to do the GOTO Divide_d2 INCF topH ; the subtraction and comparison MOVF btmL,w ; (top > btm?) in one step. ADDWF topL goto Divide_reentr ; Then, if btm > top, undo Divide_d2 MOVF btmH,w ; the subtraction by adding SUBWF topH BTFSS status,c ; top and btm back together goto Divide_less ; BSF qL,d'0' Divide_reentr BCF status,c RRF btmH RRF btmL DECFSZ count GOTO Divide_d1 RETLW 0h ; Return w/ remainder in top ; and result in q. Divide_less MOVF btmL,w ; btm > top, so ADDWF topL BTFSC status,c ; undo the subtraction by INCF topH ; adding them back together. MOVF btmH,w ADDWF topH goto Divide_reentr ; end