Sie sind auf Seite 1von 2

I've added a 16-bit square root routine (again for the 17c43) that uses successive

approximation to find the square root, the binary restoring method I'm fairly sure
would be quicker. This is the only 16-bit sqrt routine I have specifically for the
17cxx PICs, I've only included it as the original poster requested a 16-bit
routine. If you really want speed speed speed, I'd rewrite the 32-bit routine to be
16-bit.
Standard disclaimer applies

;==========================================================================
; SQRT16
;
; Calculates the square root of a sixteen bit number by successive
; approximation.
;
;
; Input in ACCaHI:ACCaLO
;
; Output in ACCbHI
;
; Also uses ACCbLO and ACCcHI.
;
;--------------------------------------------------------------------------

SQRT16:
movlw 0x80 ;
movpf WREG,ACCbLO ; set up walking tester bit.

clrf ACCbHI,w ;

movlw 0x08 ;
movpf WREG,ACCcHI ;

tstest: movfp ACCbLO,WREG ; set bit for testing.


iorwf ACCbHI,WREG ;
movpf WREG,ACCbHI ;

mulwf ACCbHI ; square the current estimate.

movfp ACCaLO,WREG ; compare PRODH:PRODL with ACCaHI:ACCaLO


subwf PRODL,WREG ;
movfp ACCaHI,WREG ;
subwfb PRODH,WREG ;

btfss ALUSTA,C ; If the result is <= input,


goto nxtbit ; ... keep this bit set.

movfp ACCbLO,WREG ; Result was > input, so reset


xorwf ACCbHI,f ; ... bit to zero.

nxtbit: rrncf ACCbLO,f ; rotate tester bit right.

decfsz ACCcHI,f ;
goto tstest ;

return
Divide 16 bits by the constant value 10 by Alec_t
from: http://www.chatzones.co.uk/discus/messages/7/DivideByTen-11542.txt

;Subroutine to divide by 10 using the binary fraction equivalent of 0.1.


;Argument: 16-bit dividend in DDHI,DDLO.
;Returns: 16-bit quotient in QTHI,QTLO.
METHOD1 CLRF QTHI ; Clear quotient accumulator
CLRF QTLO ;
MOVLW B'00011001' ; 1/10 = binary .0001100110011001 recurring
MOVWF DRHI ; ...loaded into divisor registers
MOVLW B'10011001' ;
MOVWF DRLO ;
MOVLW 16 ; Initialise loop counter (16 gives max accuracy)
MOVWF COUNT ;
SHIFT BCF STATUS,C ;
RRF DDHI,F ; Halve the dividend
RRF DDLO,F ;
RLF DRLO,F ; Shift the divisor
RLF DRHI,F ; ...so the left-most bit goes into carry
BTFSC STATUS,C ; Was the left-most bit a '1'?
CALL ADDIT ; Yes, so accumulate the partial dividend
DECF COUNT,F ; Bump the loop count
BTFSC STATUS,Z ; Is it zero?
RETURN ; Yes. Done.
GOTO SHIFT ; No. Loop for next divisor bit
RETURN
;Subroutine to accumulate partial results. Called by METHOD1.
;Argument: Current partial result in DDHI,DDLO.
;Returns: Accumulated quotient in QTHI,QTLO.
ADDIT MOVF DDLO,W ; Get the partial result LSB
ADDWF QTLO,F ; Add it to the quotient LSB
BTFSC STATUS,C ; Carry generated?
INCF QTHI,F ; Yes. Bump quotient MSB
MOVF DDHI,W ; No. Get the partial result MSB
ADDWF QTHI,F ; Add it to the quotient MSB
RETURN ; Return

;Subroutine to divide by 10 by repeated subtraction of 10.


;Argument: 16-bit dividend in DDHI,DDLO.
;Returns: 16-bit quotient in QHI,QLO, remainder in DDLO.
METHOD2 CLRF QHI ; Clear quotient registers
CLRF QLO ;
MOVLW 10 ; W = divisor
STEP SUBWF DDLO,F ; Subtract 10 from dividend LSB
BTFSC STATUS,C ; Carry?
GOTO BUMP ; No. Jump
MOVF DDHI,F ; Yes. Is dividend MSB 0?
BTFSC STATUS,Z ;
GOTO DONE ; Yes. Done
DECF DDHI,F ; No. Decrement dividend MSB
BUMP INCF QLO,F ; Bump quotient LSB
BTFSC STATUS,Z ; Is it 0?
INCF QHI,F ; Yes. Increment quotient MSB
GOTO STE

Das könnte Ihnen auch gefallen