Ascii2Float

ha valakinek van egy assemblyben írt asc2float, esetleg egy float2asc, akkor lécci dobjon már meg vele.

Ez a rutinom már lement a listán:
B       EQU     BYTE PTR
W       EQU     WORD PTR
D       EQU     DWORD PTR
Q       EQU     QWORD PTR
F       EQU     FWORD PTR
O       EQU     OFFSET
S       EQU     SMALL
L       EQU     LARGE

ValFloat        MACRO   _Float,_Src,_Save

        IFNB <_Save>                   ;; ASCII szám konvertálása
                PUSH    _Save          ;; lebegőpontos számmá
        ENDIF
        IFDIFI <_Src>,
                MOV     ESI,L O _Src
        ENDIF
                CALL    GetDouble
        IFNB <_Save>
                POP     _Save
        ENDIF
        IFDEF NoDouble
                MOV     FoundO,EAX
                MOV     FoundS,EDX
                FLD     Q [FoundO]
                FSTP    D [_Float]
        ELSE
                MOV     D [_Float],EAX
                MOV     D [_Float&+4],EDX
        ENDIF
ENDM

GetDouble:
                MOV     EDI,1086
                XOR     EAX,EAX
                XOR     EBX,EBX
                XOR     ECX,ECX
                XOR     EDX,EDX
@@1:
                MOV     AL,[ESI]
                INC     ESI
                CMP     AL,' '
                JE      @@1
                CMP     AL,'+'
                JE      @@1
                CMP     AL,'-'
                JNE     @@2
                OR      EDI,2048
                JMP     @@4
@@2:
                CMP     AL,'.'
                JNE     @@3
                INC     EBX
                JMP     @@4
@@3:
                SUB     AL,'0'
                JC      @@5
                CMP     AL,9
                JA      @@5
                CMP     EBX,1000000000
                JNC     @@4
                PUSH    EAX
                ADD     ECX,ECX
                ADC     EDX,EDX
                ADD     EBX,EBX
                MOV     EAX,ECX
                MOV     EBP,EDX
                SHLD    EDX,ECX,2
                SHL     ECX,2
                ADD     ECX,EAX
                ADC     EDX,EBP
                MOV     EBP,EBX
                SHL     EBX,2
                POP     EAX
                ADD     EBX,EBP
                ADD     ECX,EAX
@@4:
                MOV     AL,[ESI]
                INC     ESI
                JMP     @@2
@@5:
                XCHG    ECX,EAX
                AND     EBX,-2
                JZ      @@6
                DIV     EBX
                SUB     EDI,63
                MOV     EBP,EAX
                XOR     EAX,EAX
                DIV     EBX
                MOV     EDX,EBP
@@6:
                MOV     CL,31
                BSR     EBP,EDX
                JNZ     @@7
                XCHG    EDX,EAX
                SUB     EDI,32
                BSR     EBP,EDX
                JZ      @@9
@@7:
                SUB     ECX,EBP
                SHLD    EDX,EAX,CL
                SHL     EAX,CL
                ADD     EAX,EAX
                ADC     EDX,EDX
                DEC     EBX
                JS      @@8
                ADD     EDI,EBP
                SHRD    EAX,EDX,12
                SHRD    EDX,EDI,12
                RETN
@@8:
                SUB     EDI,ECX
                SHRD    EAX,EDX,12
                SHRD    EDX,EDI,12
@@9:
                RETN

De valóban igaza van a következő levélnek, hogy a konverziót az FPU-ra kell bízni.

Ehhez nem kell a lebegobontos formatum !

Megkeresed, hogy hany jegy van a tizedes pont elott, a 10-nek annyiadik hatvanyat veszed. (exp vagy szorozgatas)
X = exp10(tizedespont elotti szamjegyek szama-1)

Es akkor annyi a helyierteke a legbaloldali szamjegynek. Van Y, ami kezdetben 0.

Veszed az elso szamjegyet, megszorzod X-el, es Y-hez adod. Aztan X-et elosztod 10-el (kovetkezo helyiertek) es a kovetkezo szam X szereset is Y-hoz adod. Es igy mesz. A tizedes pontot csak at kell lepned. Es ezeket a muveleteket FPU-val vegzed. Tehat nem kell float formatum. Es akkor Y-ben lesz az eredmeny.

Az csak akkor kell, ha mas procin akarsz 3ds-t beolvasni:)

remelem ertheto volt az algoritmus. Ha nem, akkor szolj vissza.

A forditotja is kurvara egyszeru. megnezed, hogy hany jegy lesz a tizedespont elott.

Y a szam kezdetben. log10(Y) es ezt felfele kell kerekiteni. (ez lehet - is) aztan akkor X=exp10(szamjegyek szama a tizedespont elott-1) szoval el ne felejts kerekiteni !

Es akkor Y-t elosztod X-el, az eredmeny az elso szamjegy. Y=a maradek. (Azaz csokkentetted) X-et elosztod 10-el. Es ujra megcsinalod ezt. Mar az elejen kiszamoltuk, hany jegy van a 10edes pont elott, annyi jegy utan jon a tizedespont berakasa a string-be. Es utana folytatod a muveletet egy darabig. Mondjuk 20 tizedes jegyig.

Es arra kell figyelni, amikor a szam kisebb mint 1. Azaz akkor a sok 0-t ki kell irni a pont utan. Szoval van benne osszetettseg. De a forditotja egyszerubb. Osszetettseg alatt a BUG lehetosegeket ertem.

Erdemes hasznalni egyet a LIBC-bol es akkor joval egyszerubb.

és itt egy általam írt megvalósítás:
GetDouble2:
                SUB     AX,AX
                FLD1
@@1:
                LODSB
                CMP     AL,' '
                JE      @@1
                CMP     AL,9
                JE      @@1
                CMP     AL,'+'
                JE      @@1
                CMP     AL,'-'
                JNE     @@2
                FCHS
                JMP     @@1
@@2:
                FLD1
                FLDZ
@@3:
                CMP     AL,'.'
                JNE     @@4
                INC     AH
                LODSB
@@4:
                SUB     AL,'0'
                JC      @@5
                CMP     AL,9
                JA      @@5
                MOV     BYTE PTR DIGIT,AL
                FMUL    CONST10
                FIADD   DIGIT
                LODSB
                TEST    AH,AH
                JZ      @@3
                FXCH
                FMUL    CONST10
                FXCH
                JMP     @@4
@@5:
                FDIVRP  ST(1),ST
                FMULP   ST(1),ST
                RETN

CONST10         DD      10.0
DIGIT           DD      0