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)
;
;25-Sep-2000 Original version
;20-Oct-2001 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 16-bit 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 (0-borrow,
;1-no borrow)
BTFSC LOOPCOUNT, 0 ;if no borrow after 17-bit 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. 5-Dec-2004.
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 16-bit 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 (0-borrow,
;1-no borrow)
BTFSC AARGB2, 0 ;if no borrow after 17-bit 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
| file: /Techref/microchip/math/div/24by16.htm, 12KB, , updated: 2021/6/1 09:34, local time: 2025/10/27 01:59,
216.73.216.180,10-8-63-169:LOG IN
|
| ©2025 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://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 massmind.org! |
.