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: movlw .24 ; for 24 shifts movwf R5Hi ; clrf ACCaHI,f ; clear remainder. clrf ACCaLO,f ; 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. btfss ALUSTA,C ; check for remainder spill into carry. goto d2416s ; movfp ACCbLO,WREG ; subwfb ACCaLO,f ; Carry bit is the 17th bit of this subtract! movfp ACCbHI,WREG ; subwfb ACCaHI,f ; bsf ALUSTA,C ; bit is known to be zero here. goto d2416ns ; d2416s: movfp ACCbLO,WREG ; Compare remainder with divisor. subwf ACCaLO,w ; movfp ACCbHI,WREG ; subwfb ACCaHI,w ; btfss ALUSTA,C ; goto d2416ns ; (remainder < divisor), shift in a '0' movfp ACCbLO,WREG ; The remainder is larger, so subtract the subwf ACCaLO,f ; ... divisor FROM the remainder and movfp ACCbHI,WREG ; ... shift a '1' into the quot. subwfb ACCaHI,f ; d2416ns:decfsz R5Hi,f ; check all bits goto d2416lp ; rlcf ACCdLO,f ; shift in final quotient bit. rlcf ACCdHI,f ; rlcf ACCcLO,f ; return
jaakko-haakana- Says:
This code does not work if the divisor is smaller than 0x100.+Replace the five instructions at d2416s with the following to make it work (converted for 16f84):
movf ACCbHI,W ; divisor hi subwf ACCaHI,w ; remainder hi (w = remainder - divisor) btfss STATUS, C goto d2416ns ; (remainder < divisor), shift in a '0' movf ACCbLO,W subwf ACCaLO,w btfss STATUS,C
Andy David of Ultronics Ltd Says:
The above (anonymous) poster has not convinced me that the original code doesn't work -- my test cases for divisor < 0x100 are all correct.+The original code is for the 17c series pics, hence the use of the subwfb instruction. The purpose of the first 5 lines of code at d2416s is to compare the current remainder with the (constant) divisor. Using a 16-bit subtract abd checking the status of carry is standard, I can't get this code to fail. The carry that is subsequently shifted into the quotient is correct as either remainder => divisor (when remainder - divisor is +ve (>= 0) carry = 1) or remainder < divisor (carry = 0).
I've just tried several test cases with divisor < 0x100, I can't see any problem. As a benchmark I've used BaseCalc.
The alternative code looks like it will work but I don't believe there's a reason for using it; you'd normally need a good reason to replace 5 (working) lines of code with 7.
Note that if you want to use this code for 14-bit core you'll need to change more code than suggested.
Now that I've finished saying that the code works, I refer the reader to the standard disclaimer in that I'm not responsible for your use of this code. Clever people use Dimitry's, Nikolai's or Scott's code, anyway.
-- AD.
Questions:
I have tried to modify and use the code for a PIC 18F2480 (16 bit) but I can't get it to work, even with the modify of mr. jaakko-haakana. This is what I got:+DIV24_16u: movlw d'24' ; for 24 shifts movwf R5Hi ; clrf REMBH ; clear remainder. clrf REMBL ; d2416lp: rlcf DATO1L,f ; build up remainder. rlcf DATO1H,f ; rlcf DATO1U,f ; rlcf REMBL,f ; rlcf REMBH,f ; ; remainder is 16-bit, but may have spilled over into carry. btfss STATUS,C ; check for remainder spill into carry. goto d2416s ; movf DATO2L,W ; subwfb REMBL,f ; Carry bit is the 17th bit of this subtract! movf DATO2H,W ; subwfb REMBH,f ; bsf STATUS,C ; bit is known to be zero here. goto d2416ns ; d2416s: movf DATO2H,W ; divisor hi subwf REMBH,w ; remainder hi (w = remainder - divisor) btfss STATUS, C goto d2416ns ; (remainder < divisor), shift in a '0' movf DATO2L,W subwf REMBL,w btfss STATUS,C goto d2416ns ; (remainder < divisor), shift in a '0' movf DATO2L,W ; The remainder is larger, so subtract subwf REMBL,f ; ... divisor FROM the remainder and movf DATO2H,W ; ... shift a '1' into the quot. subwfb REMBH,f ; d2416ns: decfsz R5Hi,f ; check all bits goto d2416lp ; rlcf DATO1L,f ; shift in final quotient bit. rlcf DATO1H,f ; rlcf DATO1U,f ; returnCan anybody advise me about where is the error? Thanks in advance. Lorenzo. Email: tecnico at innotec.it
file: /Techref/microchip/math/div/24by16ad.htm, 8KB, , updated: 2011/1/28 04:07, local time: 2024/12/26 10:12,
52.14.125.137:LOG IN
|
©2024 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://linistepper.com/Techref/microchip/math/div/24by16ad.htm"> PIC Microcontoller Math Method </A> |
Did you find what you needed? |