Hi -- Does anyone have an assembler routine or algorithm for this? I have one b
ased on subtraction of 10X
constants but I was wondering if there is something more efficient? Microchip h
as one in their application
notes but it's only good for 2 bytes. Also, what happened to the searchable arc
hives that used to be at
iversoft.com? Please respond direct. Thanks.
On Sun, 23 Aug 1998 14:36:59 -0700 Ron Stone <spam_OUTastoneTakeThisOuTEROLS.COM> writes:
>Hi -- Does anyone have an assembler routine or algorithm for this? I
>have one based on subtraction of 10X
>constants but I was wondering if there is something more efficient?
>Microchip has one in their application
>notes but it's only good for 2 bytes.
The "BCD multiply by 2" routine presented in the application note is good
for large numbers. It is easy to expand it to more bytes. Increase the
loop count to 24 (24 bits in 3 bytes), add another rotate so all 3 bytes
of the binary number are rotated, and add more BCD digits and calls to
adjbcd.
Another method is to repeatedly divide by 10, using the remainders as BCD
digits. It takes longer but may save on code space if you already have a
suitable divison routine in the program for some other purpose.
_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]
Hi -- Does anyone have an assembler routine or algorithm for this
Here is a four byte version. If this doesn't fit your need, compare
this to the two byte version and you should be able to figure out how to
make the modifications for three bytes.
;Binary - BCD 32 bits (Full Range)
;Input in buff_4|buff_3|buff_2|buff_1,
;
;Converts to packed bcd in temp_a, temp_b, temp_c, temp_d and temp_e
;with the MSD temp_a.
;Handles full range: ff ff ff ff -> 4,294,967,295
;Also uses temp_f and count.
;2940 cycles including call and return.
;Bob Fehrenbach
Ron Stone wrote:
Hi-Does anyone have an assembler routine or algorithm for this
Here is a four byte version. If this doesn't fit your need, compare
this to the two byte version and you should be able to figure out how to
make the modifications for three bytes.
;Binary - BCD 32 bits (Full Range)
;Input in buff_4|buff_3|buff_2|buff_1,
;
;Converts to packed bcd in temp_a, temp_b, temp_c, temp_d and
temp_e ;with the MSD temp_a.
;Handles full range: ff ff ff ff -> 4,294,967,295
;Also uses temp_f and count.
;2940 cycles including call and return.
;Bob Fehrenbach
> Ron Stone wrote:
>
> Hi -- Does anyone have an assembler routine or algorithm for this
Another Post replied that you could repeatedly divide by 10 (actually
POWERS of 10) and do a BIN to BCD conversion, if you needed to have a
divide routine around anyway. I do, so I started working on this.
I need a 2 byte (actually, the data in this number will be less than
999 decimal) number converted to 3 byte BCD, not packed BCD.
Later, I will need to scale this number (probably by scaling the 2
byte BIN, it's easier) because it represents a Fahrenheit
temperature and I need to read out in Centigrade sometimes. So I'll
probably need a divide routine.
I started messing around with Divide routines today.
There is a DBL_DIVS routine in Microchip AN526. It has a note in the
header that the Numerator must be greater than the Denominator. I
checked this out, and it actually seems to give errors when the
Numerator is EQUAL to the denominator as well (I didn't check all
cases...)
Yuck:
'd103 divided by 'd100 gives Zero remainder 3 not 1
remainder 3
Double Yuck:
'd100 divided by 'd100 gives zero remainder 100 not 1 remainder
zero.
Anybody got a better routine? I'm looking for a code-efficient (not
straight-line) double precision divide routine that will handle all
cases.
-- Lawrence Lile
"The ideal design has zero parts" -
(attributed to Harold Hallikainen)
> Anybody got a better routine? I'm looking for a code-efficient (not
> straight-line) double precision divide routine that will handle all
> cases.
Sigh... I guess it's time to mention Payson's 'Wonderful Binary to BCD
routine' again. Shall I post it again? On second thought, let me throw
it out on a web page.
On Mon, 24 Aug 1998 20:42:40 +0400 Dmitry Kiryashov <.....zewsKILLspam@spam@AHA.RU> writes:
>Bob Fehrenbach wrote:
>
>; movlw h'03' ;alternative adj_bcd from Mike Keitz
Thanks for the credit, but the code has gotten so unformatted that I
can't follow it too well. Let me summarize, since this particular
routine comes up every few months.
We are looking at the 'adjbcd' process, which is part of the "BCD
multiply by 2" binary to BCD routine. What it does is prepare a packed
BCD number so that shifting it left will multiply it by 2. This should
be done by adding 3 to each digit unless the digit is less than 5 (in
which case adding 3 will leave the result less than 8):
movlw h'03' ;Adjust the low digit by adding
3
addwf INDF,w
movwf tmp_f ;Store result here for bit
test.
btfsc tmp_f,3 ;If result < 8, don't change.
movwf INDF ;Store the optimized result.
movlw h'30' ;Same process on high digit.
addwf INDF,w
movwf tmp_f
btfsc tmp_f,7
movwf INDF
Dimitry suggests:
movlw h'03' ;Adjust the low digit.
addwf INDF,f
btfss INDF,3 ;If result >= 8, keep.
subwf INDF,f ;Otherwise, de-adjust back.
movlw h'30' ;Same for high digit.
addwf INDF,f
btfss INDF,7
subwf INDF,f
My optimized routine:
movlw h'33'
addwf INDF,f ;Adjust both digits.
btfsc INDF,3 ;Low digit <8, adjust back.
andlw h'f0' ;Keep the low digit (could use
movlw h'30')
btfsc INDF,7 ;Hi digit <8, adjust back.
andlw h'0f' ;Keep the high digit (by
subtracting 0).
subwf INDF,f ;Adjust digit(s) back if still
3 in W.
So, pick your poison. They all work.
Most everyone picked up the optimization of putting the store index value
to FSR *inside* the adjbcd routine. For only a few (4 or 6) BCD digits,
consider in-lining the adjbcd routine and using direct addressing. For a
large number of BCD digits, write a loop to increment FSR and do adjbcd
repeatedly. If someone can come up with a way to combine the shifting
and adjusting (keeping a proper carry of course), that could further
save space on large numbers.
_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]
On Mon, 24 Aug 1998 12:08:31 +0000 Lawrence Lile <lilelKILLspamtoastmaster.com>
writes:
>> Ron Stone wrote:
>>
>> Hi -- Does anyone have an assembler routine or algorithm for this
>
>
>Another Post replied that you could repeatedly divide by 10 (actually
>POWERS of 10) and do a BIN to BCD conversion, if you needed to have a
>divide routine around anyway. I do, so I started working on this.
No, you divide by 10 every time. The remainders are the BCD digits, but
you get them in reverse order.
For example, consider 936.
936 div 10 = 93 remainder 6
93 div 10 = 9 remainder 3
9 div 10 = 0 remainder 9
If you want a variable length result, you can stop when the divide result
is zero. Or do the process a fixed number of times, and the result will
have leading zero digits since 0 div 10 = 0 remainder 0.
Put the remainders in order and you have 9 3 6. If you're displaying on
an HD44780 LCD screen, you can set it to move the cursor from right to
left, and write the digits as they are computed. Otherwise you'd
probably need to save them in RAM for output in the usual left to right
order.
Since the division is always be 10 a simple long division routine can be
implemented with just a single byte subtract and test.
_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]
>You gave me another idea how to optimize code.
>Just idea not been tested.
It looks like it will work. Probably about the best it can be done in
terms of speed (other than unrolling the loop entirely).
>; buff_1234 values will be corrupted.
If you'd like the binary value to remain the same after conversion, make
it shift in a circle like this:
rlf buff_4,w ;<-- Add this instr, picks up high
bit.
rlf buff_1,f
rlf buff_2,f
rlf buff_3,f
rlf buff_4,f
rlf temp_e,f
etc.
After 32 loops, the value in buff will have shifted all the way around,
so it would be the same as at the start. The cost is one more
instruction which is executed 32 times.
> clrf count
> bsf count,5 ;32.
Cute, but movlw/movwf is the same performance and a lot easier to
understand.
_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]