;*******************************************************************
; Double Precision Division
; 16位BIN数除法
; ( Optimized for Speed : straight Line Code )
;
;*******************************************************************;
; Division : ACCb(16 bits) / ACCa(16 bits) -> ACCb(16 bits) with
; Remainder in ACCc (16 bits)
; (a) Load the Denominator in location ACCaHI & ACCaLO ( 16 bits )
; (b) Load the Numerator in location ACCbHI & ACCbLO ( 16 bits )
; (c) CALL D_div
; (d) The 16 bit result is in location ACCbHI & ACCbLO
; (e) The 16 bit Remainder is in locations ACCcHI & ACCcLO
;
; Performance :
; Program Memory : 370
; Clock Cycles : 263
;
; NOTE :
; The performance specs are for Unsigned arithmetic ( i.e,
; with "SIGNED equ FALSE ").
;
;*******************************************************************;
;
ACCaLO equ 10
ACCaHI equ 11
ACCbLO equ 12
ACCbHI equ 13
ACCcLO equ 14
ACCcHI equ 15
ACCdLO equ 16
ACCdHI equ 17
temp equ 18
sign equ 19
;
org 0
;*******************************************************************
SIGNED equ FALSE ; Set This To 'TRUE' if the routines
; ; for Multiplication & Division needs
; ; to be assembled as Signed Integer
; ; Routines. If 'FALSE' the above two
; ; routines ( D_mpy & D_div ) use
; ; unsigned arithmetic.
;*******************************************************************;
; division macro
;
divMac MACRO
LOCAL NOCHK
LOCAL NOGO
;
bcf STATUS,CARRY
rlf ACCdLO
rlf ACCdHI
rlf ACCcLO
rlf ACCcHI
movf ACCaHI,w
subwf ACCcHI,w ;check if a>c
btfss STATUS,Z_bit
goto NOCHK
movf ACCaLO,w
subwf ACCcLO,w ;if msb equal then check lsb
NOCHK
btfss STATUS,CARRY ;carry set if c>a
goto NOGO
movf ACCaLO,w ;c-a into c
subwf ACCcLO
btfss STATUS,CARRY
decf ACCcHI
movf ACCaHI,w
subwf ACCcHI
bsf STATUS,CARRY ;shift a 1 into b (result)
NOGO
rlf ACCbLO
rlf ACCbHI
;
ENDM
;
;*******************************************************************
; Double Precision Divide ( 16/16 -> 16 )
;
; ( ACCb/ACCa -> ACCb with remainder in ACCc ) : 16 bit output
; with Quotiont in ACCb (ACCbHI,ACCbLO) and Remainder in ACCc (ACCcHI,ACCcLO).
;
; NOTE : Before calling this routine, the user should make sure that
; the Numerator(ACCb) is greater than Denominator(ACCa). If
; the case is not true, the user should scale either Numerator
; or Denominator or both such that Numerator is greater than
; the Denominator.
;
;
setup
movlw D'16' ; for 16 shifts
movwf temp
movf ACCbHI,w ;move ACCb to ACCd
movwf ACCdHI
movf ACCbLO,w
movwf ACCdLO
clrf ACCbHI
clrf ACCbLO
retlw 0
;
;*******************************************************************
;
neg_A
comf ACCaLO ; negate ACCa ( -ACCa -> ACCa )
incf ACCaLO
btfsc STATUS,Z_bit
decf ACCaHI
comf ACCaHI
retlw 0
;
;*******************************************************************
;
D_divF
;
IF SIGNED
CALL S_SIGN
ENDIF
;
call setup
clrf ACCcHI
clrf ACCcLO
;
; use the mulMac macro 16 times
;
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
divMac
;
IF SIGNED
btfss sign,MSB ; check sign if negative
retlw 0
goto neg_B ; negate ACCa ( -ACCa -> ACCa )
ELSE
retlw 0
ENDIF
;
;*******************************************************************
; Assemble this section only if Signed Arithmetic Needed
;
IF SIGNED
;
S_SIGN
movf ACCaHI,W
xorwf ACCbHI,W
movwf sign
btfss ACCbHI,MSB ; if MSB set go & negate ACCb
goto chek_A
;
comf ACCbLO ; negate ACCb
incf ACCbLO
btfsc STATUS,Z_bit
decf ACCbHI
comf ACCbHI
;
chek_A
btfss ACCaHI,MSB ; if MSB set go & negate ACCa
retlw 0
goto neg_A
;
ENDIF
;
;*******************************************************************
; 测试程序(注意用法,ACCb/ACCa,结果放在ACCb里,余数放在ACCc里)
;*******************************************************************
; Load constant values to ACCa & ACCb for testing
;
main
movlw 1
movwf ACCaHI
movlw 0FF ; loads ACCa = 01FF
movwf ACCaLO
;
movlw 07F
movwf ACCbHI
movlw 0FF ; loads ACCb = 7FFF
movwf ACCbLO
call D_divF ; remainder in ACCc. Here ACCb =0040 & ACCc=003F
;
self goto self ;如不是测试程序,本句无用
;
org PIC54
LIST p=16c54
goto main
END
;****************************************************************