using decimals for huge numbers

Started by whakamaru, January 11, 2012, 09:45:07 PM

Previous topic - Next topic

whakamaru

Many Euler problems involve huge numbers which are a hastle in 16-bit, so I was pleased to work out a way using decimals instead.
The programme has solved something, and now we need to count the successes... so...
    mov  bl,a                decimals always involve dividing by ten
    mov  si,f7               point to a convenient space.  I usually use the PSP
&  inc   byte ptr[si]      add to the total
    cmp [si],bl              is it ten?
    jnz    ???                   no, go back to the main programme
    mov [si],bh             yes, make the digit zero (BH=0)
    dec  si                     and move to next digit
    jmp    &

it will keep going...to a nine digit number in my solution a variation of PE #92

dedndave

well - there are a number of alternatives
however, BCD math is good for some Euler problems

1) write 32-bit programs
2) use 32-bit registers in 16-bit programs
3) use the FPU, which can handle several BCD digits

whakamaru

How can I use 32-bit registers in 16-bit?  Use machine code maybe?   Where can I get the machine code hex  from? ie, is PUSH EAX  the same as PUSH AX?
What difference would BCD make to the lines?  Save a few bytes of memory maybe, but makes it much harder to extract to display?
Although I know the Intel definitions for AAA, AAM, AAS and AAM, I still don't know what they actually do!

dedndave

this should allow the use of 32-bit registers:
        .MODEL  Small
        .STACK  1024
        .DOSSEG
        .386

once you do that, you can use either PUSH AX or PUSH EAX

as for BCD or "packed decimal", it is actually easier to convert to ASCII strings
although, it is not the most efficient code when multiplying or dividing
the FPU can perform BCD math for you
have a look at Ray's tutorial...
http://www.ray.masmcode.com/BCDtut.html
http://www.ray.masmcode.com/

FORTRANS

#4
Hi,

   AAA, AAD, AAM, and AAS are instructios to operate on unpacked
BCD operands.  The following text may help?  And I wrote a
program to use AAA in the following thread.  Rather blunt, but
should be easy to decipher.

http://www.masm32.com/board/index.php?topic=12771.30

HTH,

Steve N.

"AAA","ASCII Adjust after Addition:

   Adjusts the result in AL, after two unpacked
BCD digits have been added together.  If AL > 9, AL is adjusted
to the proper BCD digit (AL - 10), AH is incremented, and the
Carry and Aux Carry flags are set.  If AL < 10, AL and AH are
unaffected, and the Carry and Aux Carry flags are cleared.

SAMPLE CODE

MOV AH,07
MOV AL,08
ADD AL,AH  ;15D IN AL
SUB AH,AH  ;AH=0
AAA
OR AX,3030 ;Convert digits to ASCII","?     ? ? B ? M"@

"AAA+","AAA continued.
   His example can be bad.  AAA uses the CY and AC flags set
by the ADD to make the correction.  My code was.

ADD     AL,[DI] ; If there is any existing data.
XOR     AH,AH
AAA             ; Adjust after addition.

   And that produced the wrong result.  Note that AH must be
zeroed as AAA increments AH contents, rather than setting AH
to zero or one.  The working code is now.

XOR     AH,AH   ; Needed as AAA increments AH contents.
ADD     AL,[DI] ; If there is any existing data.
AAA             ; ASCII Adjust after Addition.

bytes  8088   186   286   386   486   Pentium
1        8     8     3     4     3     3  NP",""@

"AAD","ASCII Adjust before Division:

   Converts unpacked BCD digits in AH and AL
to a single binary value in preparation for the DIV
instruction.  AL is set to 10*AH + AL.  AH is cleared.

SAMPLE CODE

MOV AH,'7'
MOV AL,'6'
AND AX,0F0FH ; Convert ASCII to BCD 0706
AAD          ; Convert to 004C

bytes  8088   186   286   386   486   Pentium
2       60    15    14    19    14    10  NP

(second byte is multiplier)","?     M M ? M ?"@

"AAM","ASCII Adjust after Multiply:

   Adjusts the results in AX after two unpacked
BCD digits have been multiplied together.  Doesn't have to
be used only after multiplication.  Reverses what AAD does.
AL is divided by 10 leaving the quotient (MSD) in AH and
the remainder (LSD) in AL.  (Opposite of DIV Byte.)

SAMPLE CODE

MOV AX,004C; AX=76 DEC
AAM        ; NOW = 0706h
OR AX,3030 ; NOW = 3736h

bytes  8088   186   286   386   486   Pentium
2       83    19    16    17    15    18  NP

(second byte is divisor)","?     M M ? M ?"@

"AAS","ASCII Adjust after Subtraction:

   Adjusts the results in AX after a subtraction.
If the BCD subtraction caused a decimal carry, AAS adjusts AL,
decrements AH, and sets the Carry and the Aux Carry flags.
Else AL and AH are unaffected, and the two flags are cleared.

SAMPLE CODE

MOV AH,01 ; AH=BCD 1
MOV AL,04 ; AL=BCD 4
MOV BL,07
SUB AL,BL ; AL <-AL-BL (14-7)
AAS       ; AX=0007 BCD
OR AX 3030; ASCII 3037

bytes  8088   186   286   386   486   Pentium
1        8     7     3     4     3     3  NP","?     ? ? B ? M"@

dedndave

oops - forgot DAA, DAS   :P

nice tutorial, though   :U

FORTRANS

Quote from: dedndave on January 24, 2012, 04:35:05 PM
oops - forgot DAA, DAS   :P

Hi,

   Well, he asked for the upacked BCD guys.  But look below.

Quote
nice tutorial, though   :U

Thanks,

Steve

"DAA","Decimal Adjust after Addition:

   Adjusts the sum in AL, after two packed BCD values
have been added.  Converts the sum to two packed BCD
digits in AL.  The Carry flag is set if a carry occured.


bytes  8088   186   286   386   486   Pentium
1        4     4     3     4     2     3  NP","?     M M B M B"@

"DAS","Decimal Adjust after Subtraction:

   Converts the result of subtracting two packed BCD
operands in AL to two valid packed BCD digits.  The
Carry flag is set if a borrow was needed.  Packed BCD
(Binary Coded Decimal) consists of a valid decimal
digit in each half byte of the byte operand.


bytes  8088   186   286   386   486   Pentium
1        4     4     3     4     2     3  NP","?     M M B M B"@