from by Nikolai
Golovchenko
FXD2416U: CLRF REMB0 CLRF REMB1 MOVLW 24 MOVWF LOOPCOUNT LOOPU2416 RLF ACCB0, W ;left shift of accb0's msb to reminder RLF REMB1, F RLF REMB0, F MOVF BARGB1, W ;REMB = BARGB SUBWF REMB1, F MOVF BARGB0, W BTFSS _C INCFSZ BARGB0,W SUBWF REMB0, F BTFSC _C GOTO UOK46LL ;if no borrow MOVF BARGB1, W ;REMB += BARGB ADDWF REMB1, F MOVF BARGB0, W BTFSC _C INCFSZ BARGB0,W ADDWF REMB0, F BCF _C UOK46LL RLF AARGB2, F RLF AARGB1, F RLF AARGB0, F DECFSZ LOOPCOUNT, F GOTO LOOPU2416 RETURN
The routine above is actually 24 by 15 bits division. Below is a 24 by 16 bits division routine:;Inputs: ; Dividend  AARGB0:AARGB1:AARGB2 (0  most significant!) ; Divisor  BARGB0:BARGB1 ;Temporary: ; Counter  LOOPCOUNT ; Remainder REMB0:REMB1 ;Output: ; Quotient  AARGB0:AARGB1:AARGB2 ; ; Size: 28 ; Max timing: 4+24*(6+6+4+3+6)1+3+2=608 cycles (with return) ; Min timing: 4+24*(6+6+5+6)1+3+2=560 cycles (with return) ; FXD2416U: CLRF REMB0 CLRF REMB1 MOVLW 24 MOVWF LOOPCOUNT LOOPU2416 RLF AARGB2, F ;shift left divider to pass next bit to remainder RLF AARGB1, F ;and shift in next bit of result RLF AARGB0, F RLF REMB1, F ;shift carry into remainder RLF REMB0, F RLF LOOPCOUNT, F ;save carry in counter MOVF BARGB1, W ;substract divisor from remainder SUBWF REMB1, F MOVF BARGB0, W BTFSS _C INCFSZ BARGB0, W SUBWF REMB0, W ;keep that byte in W untill we make sure about borrow SKPNC ;if no borrow BSF LOOPCOUNT, 0 ;set bit 0 of counter (saved carry) BTFSC LOOPCOUNT, 0 ;if no borrow GOTO UOK46LL ;jump MOVF BARGB1, W ;restore remainder if borrow ADDWF REMB1, F MOVF REMB0, W ;read high byte of remainder to W ;to not change it by next instruction UOK46LL MOVWF REMB0 ;store high byte of remainder CLRC ;copy bit 0 to carry RRF LOOPCOUNT, F ;and restore counter DECFSZ LOOPCOUNT, f ;decrement counter GOTO LOOPU2416 ;and repeat loop if not zero RLF AARGB2, F ;shift in last bit of result RLF AARGB1, F RLF AARGB0, F RETURN
Nikolai Golovchenko shares this code:
Here is a slightly optimized version  1 instruction shorter, 24 cycles faster! ;Inputs: ; Dividend  AARGB0:AARGB1:AARGB2 (0  most significant!) ; Divisor  BARGB0:BARGB1 ;Temporary: ; Counter  LOOPCOUNT ; Remainder REMB0:REMB1 ;Output: ; Quotient  AARGB0:AARGB1:AARGB2 ; ; Size: 27 ; Max timing: 4+24*(6+6+4+3+5)1+3+2=584 cycles (with return) ; Min timing: 4+24*(6+6+5+5)1+3+2=536 cycles (with return) ; ;25Sep2000 Original version ;20Oct2001 Made the loop one instruction shorter, comments ; review. FXD2416U: CLRF REMB0 CLRF REMB1 MOVLW 24 MOVWF LOOPCOUNT LOOPU2416 RLF AARGB2, F ;shift dividend left to move next bit to remainder RLF AARGB1, F ;and shift in next bit of result RLF AARGB0, F ; RLF REMB1, F ;shift carry (next dividend bit) into remainder RLF REMB0, F RLF LOOPCOUNT, F ;save carry in counter, since remainder ;can be 17 bit long in some cases (e.g. ;0x800000/0xFFFF) MOVF BARGB1, W ;substract divisor from 16bit remainder SUBWF REMB1, F ; MOVF BARGB0, W ; BTFSS STATUS, C ; INCFSZ BARGB0, W ; SUBWF REMB0, F ; ;here we also need to take into account the 17th bit of remainder, which ;is in LOOPCOUNT.0. If we don't have a borrow after subtracting from lower ;16 bits of remainder, then there is no borrow regardless of 17th bit ;value. But, if we have the borrow, then that will depend on 17th bit ;value. If it is 1, then no final borrow will occur. If it is 0, borrow ;will occur. SKPNC ;if no borrow after 16 bit subtraction BSF LOOPCOUNT, 0 ;then no no borrow in result. Overwrite ;LOOPCOUNT.0 with 1 to indicate no ;borrow. ;if borrow did occur, LOOPCOUNT.0 will ;hold the eventual borrow value (0borrow, ;1no borrow) BTFSC LOOPCOUNT, 0 ;if no borrow after 17bit subtraction GOTO UOK46LL ;skip remainder restoration. ADDWF REMB0, F ;restore higher byte of remainder. (w ;contains the value subtracted from it ;previously) MOVF BARGB1, W ;restore lower byte of remainder ADDWF REMB1, F ; UOK46LL CLRC ;copy bit LOOPCOUNT.0 to carry RRF LOOPCOUNT, F ;and restore counter DECFSZ LOOPCOUNT, f ;decrement counter GOTO LOOPU2416 ;and repeat loop if not zero. carry ;contains next quotient bit (if borrow, ;it is 0, if not, it is 1). RLF AARGB2, F ;shift in last bit of quotient RLF AARGB1, F RLF AARGB0, F RETURN
Nikolai Golovchenko shares this code:
Well, the routine can be made even simpler! This version is 5 instructions shorter and 48 cycles faster. Thanks to Zlatko Petkov for an idea of removing the extra shifts after the loop. Nikolai Golovchenko. 5Dec2004.+FXD2416U: CLRF REMB0 CLRF REMB1 MOVLW .24 MOVWF LOOPCOUNT LOOPU2416 RLF AARGB2, W ;shift dividend left to move next bit to remainder RLF AARGB1, F ; RLF AARGB0, F ; RLF REMB1, F ;shift carry (next dividend bit) into remainder RLF REMB0, F RLF AARGB2, F ;finish shifting the dividend and save carry in AARGB2.0, ;since remainder can be 17 bit long in some cases ;(e.g. 0x800000/0xFFFF). This bit will also serve ;as the next result bit. MOVF BARGB1, W ;substract divisor from 16bit remainder SUBWF REMB1, F ; MOVF BARGB0, W ; BTFSS STATUS, C ; INCFSZ BARGB0, W ; SUBWF REMB0, F ; ;here we also need to take into account the 17th bit of remainder, which ;is in AARGB2.0. If we don't have a borrow after subtracting from lower ;16 bits of remainder, then there is no borrow regardless of 17th bit ;value. But, if we have the borrow, then that will depend on 17th bit ;value. If it is 1, then no final borrow will occur. If it is 0, borrow ;will occur. These values match the borrow flag polarity. SKPNC ;if no borrow after 16 bit subtraction BSF AARGB2, 0 ;then there is no borrow in result. Overwrite ;AARGB2.0 with 1 to indicate no ;borrow. ;if borrow did occur, AARGB2.0 already ;holds the final borrow value (0borrow, ;1no borrow) BTFSC AARGB2, 0 ;if no borrow after 17bit subtraction GOTO UOK46LL ;skip remainder restoration. ADDWF REMB0, F ;restore higher byte of remainder. (w ;contains the value subtracted from it ;previously) MOVF BARGB1, W ;restore lower byte of remainder ADDWF REMB1, F ; UOK46LL DECFSZ LOOPCOUNT, f ;decrement counter GOTO LOOPU2416 ;and repeat the loop if not zero. RETURN
Fathy Lotfy Samaha of Freelancer Says:
Thanks so much, this is a much simple routine,+
but it did not work with me until I changed
the first line to :movlw .24 ,I am using MPASM and MPLAB, it recogonize
the decimal numbers precedded with a dot .
Questions:
Dear Piclist People:
Thanks to all for sharing your knowledge. I was wondering if some of you have had a problem like the one I describe below. Any help will be welcomed!
Iâ¬™m dealing with integer unsigned binary division using a PIC. I implemented 24/24 bit division and everything went ok. But when performing 24/16 bit division, something goes wrong.
The dividend (numerator) is a 24 bit constant, but the divisor (denominator) is a variable number. When this denominator takes a low value (but still 16 bit value), say 10700 i.e., the error in the result is quite a lot, and it becomes bigger as the difference between both operands does too. Is there a solution to this?
Thanks again for your help. Greetings!
Comments:
reference the LAST code segment.
Using a PIC18F4520, please note the code changes.
THANKS YOU all for saving me a lot of work.LOOPU2416 bcf CARRY ; addition of code line rlcf BSR1_Larger24Lo,W ; shift dividend left to move next bit to remainder rlcf BSR1_Larger24Mi,F rlcf BSR1_Larger24Hi,F rlcf BSR1_Remain16Lo,F ; shift carry (next dividend bit) into remainder rlcf BSR1_Remain16Hi,F rlcf BSR1_Larger24Lo,F ; finish shifting the dividend and save carry in ; BSR1_Larger24Lo.0, ; since remainder can be 17 bit long in some cases ; (e.g. 0x800000/0xFFFF). This bit will also serve ; as the next result bit.I apologise for spiling the convention in MY labels, but you can work backwards from the origonal code.
Rick
Sorry, I forgot...+
Also, for PIC184520...
replace SKPNC with btfsc CARRY; SKPNC ;if no borrow after 16 bit subtraction btfsc CARRY ; if no borrow after 16 bit subtraction
See also:
file: /Techref/microchip/math/div/24by16.htm, 12KB, , updated: 2013/8/12 09:18, local time: 2020/4/6 12:06,

©2020 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/techref/microchip/math/div/24by16.htm"> PIC Math Divide 24 bits by 16</A> 
Did you find what you needed? 
Welcome to massmind.org! 
Welcome to techref.massmind.org! 
.