## BCD division by 2

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
Twilighte
Game master
Posts: 819
Joined: Sat Jan 07, 2006 12:07 am
Location: Luton, UK
Contact:

### BCD division by 2

Whats the simplest way to divide a single BCD number by 2 or 4 ?

BCD is a special mode in the 6502 that holds decimal numbers in Bytes as two 4 bit digits. So that maximum value is 99 and minimum is 00.
In BCD mode only ADC and SBC behave appropriately like setting carry if the result of the ADC takes the number over 99.

I can't use LSR since it doesn't operate in the right way. For example 99/2 in BCD mode using LSR would give me 4C which is clearly wrong, and should be 49.

I tried using a simple loop like this preloading A with the BCD number..

Code: Select all

``````      LDX #00
SED
SEC
loop1 INX
SBC #02
BCS loop1
CLD``````
But it fails because whilst the accumulated number in X is correct, it is not BCD encoded.
The only way i can see is this..

Code: Select all

``````      STA BCDNumber
SED
LDA #00
STA Result
CLC
loop1 LDA Result
STA Result
LDA BCDNumber
SEC
SBC #02
STA BCDNumber
BCS loop1
CLD``````
But this seems extremely long winded just to divide the BCD number by 2 even in its optimised form, any thoughts? Chema
Game master
Posts: 2468
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:
Tricky one...

I don't see an easy (I mean compact and fast) way of doing this, but searching a bit with Google I found this:

http://www.atarimagazines.com/compute/i ... OUTINE.php

It is a routine to convert BCD to binary, but he is using the trick of dividing by two, so we can borrow this part, I assume. The explanation that might be useful is this one:
"The eight bit "weights" in a byte of memory that represent a binary number are 1, 2, 4, 8, 16, 32, 64, and 128, proceeding from the right-most bit to the left-most bit. Clearly, shifting the number to the right divides each bit weight by two. That is why an LSR or an ROR instruction may be used to divide a binary number by two. However, if the same memory location represents a BCD number, then the bit weights are 1, 2, 4, 8, 10, 20, 40, 80. consequently, a shift-right or a rotate-right instruction results in division-by-two only for bits zero, one, two, three, five, six, and seven. Shifting bit four (with a weight of ten) to the right changes its weight to eight. Eight is three more than five, the number you usually get when you divide ten by two. So, the trick to dividing a BCD number by two is to shift right or rotate right as usual, but if a one is shifted from bit four to bit three, then you must subtract three from the shifted-right result to get the correct answer. That's it folks. I wish I could say it was my idea, but I found it in Peatman's5 book."
It includes some code, so it could be worth having a look.

Cheers

Twilighte
Game master
Posts: 819
Joined: Sat Jan 07, 2006 12:07 am
Location: Luton, UK
Contact:
Thats logical until the end. Done the maths and he is right, subtracting 3 if a carry from Bit4 to 3 occurs is correct but looks like a kludge or bodge, even if it does work.

In code this is difficult because we cannot examine bits (apart from B6 and 7 with BIT) without affecting the Accumulator on the 6502..

Code: Select all

``````      LSR
STA temp01
AND #08
CMP #8
LDA temp01
BCC skip1
SBC #03
skip1 ``````
And that final SBC must be in binary, not BCD.
Definately less readable than previous code but definately faster and shorter, thanks Chema Dbug
If you are going to use BCD, make sure you don't do anything wrong in your interrupt handlers, or that you stop interrupts before Was bitten by that when I worked on my minigames 