ON 20091123@3:25:20 PM at page:
On a web page you were interested in at:
http://www.piclist.com/microchip/math/radix/b2a-16b5dlzd.htm#40139.4336458333
James Newton[JMN-EFP-786] published post 40139.4336458333
There are several bugs/typos in this code. Here is the code I am using with a pic16f690 and the gpasm(Gnu/Linux) compiler. There are some changes in that I favour null terminated strings...
; This routine accepts a 16-bit number in hiB, lowB and converts it into
; a null terminated ASCII text string located at the address "buffer."
; The routine destroys the contents of hiB, lowB.
PRDEC:
clrf flags ; Clear zs flag.
clrf dec_no ; Clear decade no.
movlw buffer ; get buffer addr
movwf FSR ; set-up indirect adressing
prdeclp:
movf dec_no,w
call decade ; table lookup
movwf tempH ; save it
incf dec_no,f ; Get 2nd digit of decade no.
movf dec_no,w ; incremented decade counter
call decade ; table lookup
movwf tempL ; save it
; call d_point ; Insert decimal point.
call sub_it ; Divide hiB,lowB by tempH,tempL
movf INDF,w ; get the result
btfsc flags,0 ; If zs = 0 AND digit = 0 then
goto prdecnzs
btfsc STATUS,2 ; digit is a leading zero to be
goto prdecnz
prdecnzs: ;no leading 0 supression
movwf INDF
movlw a'0'
addwf INDF,f ; add ascii '0'
incf FSR,f ; Point to next memory location.
bsf flags,0 ; First non-zero digit sets zs bit.
prdecnz:
incf dec_no,f ; Next decade.
movlw 0x08 ; If dec_no = 8, we're down to ones.
subwf dec_no,w
btfss STATUS,2
goto prdeclp ; Otherwise, do next decade.
incf dec_no,f ; Update decade number for d_point.
; call d_point ; Decimal point here?
movf lowB,w
movwf INDF
movlw a'0'
addwf INDF,f ; add ascii '0'
incf FSR,f
movlw 0x00
movwf INDF ; null terminated
call PRLINE
retlw 0x00
; This routine performs division by iterated subtraction. It is efficient
; in this application because the dividend and divisor keep getting smaller
; as BIN_ASC runs, so the quotient is never larger than nine. A general-
; purpose division routine would be slower (and longer).
sub_it:
clrf INDF ; Clear to track no. of subtractions.
sub_it_loop:
movf tempL,w ; Subtract LSB.
subwf lowB,f
btfsc STATUS,0 ; If no borrow, continue w/MSB.
goto sub_it_skip
movlw 0x01 ; Otherwise borrow from MSB.
subwf hiB,f
btfsc STATUS,0 ; If borrow causes a carry, then
goto sub_it_skip
incf hiB,f ; add numbers back and return.
movf tempL,w
addwf lowB,f
retlw 0x00
sub_it_skip:
movf tempH,w ; Subtract MSB.
subwf hiB,f
btfsc STATUS,0 ; If no borrow, subtract again.
goto sub_it_skip2
movf tempL,w
addwf lowB,f ; Otherwise, undo the subtraction
btfsc STATUS,0 ; by adding entire 16-bit no.
incf hiB,f ; back together and return.
movf tempH,w
addwf hiB,f
retlw 0x00
sub_it_skip2
incf INDF,f ; No borrow, so do it again.
goto sub_it_loop
; This routine adds a decimal point in the location set by "fix" in the
; equates at the beginning of the program. The location of the decimal point
; is in front of the "fix"ed digit, numbered starting with 0. If you fix the
; point at 0, the first (0th) character in the string produced by BIN_ASC
; will be a decimal point. If you don't want a decimal point, either move
; it out of range (fix = 6), or delete this routine and the "call d_point"
; in the body of BIN_ASC above.
d_point
movlw fix*2+1
subwf dec_no,w
btfss STATUS,2
retlw 0x00
bsf flags,0
movlw a'.'
movwf INDF
incf FSR,f
retlw 0x00
; Table consisting of values 10,000, 1000, 100, 10, and 1.
decade addwf PCL,f
retlw d'39' ; 10,000
retlw d'16'
retlw d'3' ; 1,000
retlw d'232'
retlw d'0' ; 100
retlw d'100'
retlw d'0' ; 10
retlw d'10'
retlw d'0' ; 1
retlw d'1'
|Delete 'P-' before: '' but after: '