i work on assembly for the X86 platform and i got an issue with doing bcd for numbers bigger than 99.
i got in 'AX' 123 (decimal) and i added to it 5 (decimal) then i did 'aaa' but instead of the result to be 128 its 0106.
i saw the algorithm and understood why but how i do 'aaa' to number over 99
that's my code:
mov ax,123
add ax,5
aaa
i tried to divide 'AX' in 0ah to separate the number and use 'aad' but i saw that it's forbiden for numbers over 99.
The 'AAA" instruction ("ASCII Adjust After Addition") only cares about the value in the lowest 4 bits of
AL
(it's literally "if(AL & 0x0F > 9) AX += (1 << 8) + (1 << 4) - 10;
", or "if the previous addition caused the lowest nibble/digit to overflow; then subtract 10 from the lowest nibble/digit and add 1 to second nibble/digit to fix up the carry that should've happened but didn't, then add 1 plus the carry from second nibble/digit to the third nibble/digit while most people wish this didn't happen").For 8-bit packed BCD addition (e.g. one digit in the lowest nibble of AL and another digit in the highest nibble of AL) this is a major pain in the neck - you have to store the first nibble somewhere then shift the value in AL to the right and do a second
aaa
to fix up the second nibble. This can be done with rotates - e.g.aaa
thenror ax,4
thenaaa
thenrol ax,4
.For 8-bit unpacked BCD addition (e.g. one digit in the lowest nibble of AL and another digit in the lowest nibble of AH) it's mostly the same major pain in the neck.
For "12-bit or larger" packed BCD addition it goes from bad to worse because first
aaa
causes the third nibble/digit to be potentially corrupted (increased by 1 too many if the first nibble overflowed), the secondaaa
potentially corrupts the fourth nibble/digit, etc.For "12-bit or larger" unpacked BCD addition it goes from bad to worse because (for 16-bit code) now your digits have to be spread across multiple registers and you end up shuffling values into/out of AL just to use the
aaa
instruction.The only sane solution is to never use
aaa
unless you're doing 4-bit addition (which is why it got removed in 64-bit code - nobody used it anyway).The best alternative is to convert from BCD to normal integer at first sight, then do all the calculations using normal integers, then convert from normal integer back into BCD at the last possible opportunity. This approach can be especially nice if you can use the FPU - e.g.
fbld
to load an 18-digit (72 bit) packed BCD value into an FPU register while converting it into a normal floating point value andfbstp
to convert a normal floating point value into BCD and store it.Anyway...
If the original value/s being added were valid BCD, then you might get something like:
However, it this is a "lucky case" because the result fits in 2 digits. It could easily be more like: