flat assembler
Message board for the users of flat assembler.

Index > Main > floats for FASMLIB 0.6

Author
Thread Post new topic Reply to topic
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 20 Mar 2007, 22:10
what about writing\reading Float numbers?

and what about 64 bits numbers....
Post 20 Mar 2007, 22:10
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 20 Mar 2007, 22:43
i don't regard 64bit numbers as important for now.

floats surely are important, but unfortunatelly i lack skill to write good converting routine. I asked tomasz to provide me some, but he seems to be busy right now Sad

Float numbers will surely make it into FASMLIB as soon as possible.
Post 20 Mar 2007, 22:43
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 21 Mar 2007, 10:25
vid wrote:

Float numbers will surely make it into FASMLIB as soon as possible.


i am really need them, and some people too...
we will wait...
Post 21 Mar 2007, 10:25
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 21 Mar 2007, 11:09
sorry, i'm afraid i am not the right one to do it. I am afraid i wouldn't be able to do it properly.

Another solution could be stealing someone's other algorithms
Post 21 Mar 2007, 11:09
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4623
Location: Argentina
LocoDelAssembly 21 Mar 2007, 14:16
Looking at libc source and doing the appropiate port? I think that if you mention that your algo is based on libc you will have no trouble, the license must allow you to do that, isn't it? Otherwise wait for Tomasz Razz
Post 21 Mar 2007, 14:16
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 21 Mar 2007, 15:08
i DID look at (g)libc sources. Try looking at them yourself and you will see reason why i didn't choose this way Wink Laughing
Post 21 Mar 2007, 15:08
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 21 Mar 2007, 18:03
maybe I can write something... I will think about this... maybe...
Post 21 Mar 2007, 18:03
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 21 Mar 2007, 18:30
dead_body: i would be glad if you could.

First thing to think about is whether to use FPU or not. if you use FPU you get rounding problems. Doing it just with normal instruction is bigger problem Smile

if you would be interested, please let me know. You would need to adhere few rules, so it can be used (mostly, support few formats needed)
Post 21 Mar 2007, 18:30
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 22 Mar 2007, 07:32
vid wrote:
if you would be interested, please let me know. You would need to adhere few rules, so it can be used (mostly, support few formats needed)


what rules? i have an interest...
Post 22 Mar 2007, 07:32
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 22 Mar 2007, 10:41
as first, you could try to do conversion from ASCII format to floating point. Conversion to ascii is harder, as we must support more options, and i must think about it a little bit more.

Here are rules for "extconv.fp2t string, buflen"

- converts ascii string to tbyte floating point number
- accepts forms "-10", "4.51332533", "+3.4", "1e20", "-5.3e-20", "4e+30"
- number of digits is not limited, so even thousand zeroes followed by real number should be converted just like the zeroes weren't there. same applies to exponent.
- takes 2 arguments: pointer to ascii string and length of string buffer
- function cannot access memory behind end of buffer.
- if first char isn't valid FP number character, function returns CF=1, and EAX=ERR_NOT_FLOAT
- any unexpected (non-float) character can terminate conversion. For eample in "10d", only "10" is converted.
- if number is not completed ("10.", "10.z", "1.5e-"), function returns ERR_BAD_FLOAT
- if number doesn't fit into register, function returns ERR_OUT_OF_RANGE

that is all that comes to my mind. if there are any problems just ask


Last edited by vid on 24 Mar 2007, 12:09; edited 1 time in total
Post 22 Mar 2007, 10:41
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
dead_body



Joined: 21 Sep 2005
Posts: 187
Location: Ukraine,Kharkov
dead_body 24 Mar 2007, 11:48
what it must return?
result in ST0?
or maybe it will recieve a pointer to var(tbyte) and there we will store our number?(and here BCD or extended float)
Post 24 Mar 2007, 11:48
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7103
Location: Slovakia
vid 24 Mar 2007, 11:55
in case of error CF=1, EAX=error code (ERR_SOMETHING constant)
in case of no error CF=0, ST0=converted number.
All other general purpose registers should be preserved.

i think ST0 is better than pointer to variable, often you want to use number just after converting. If no, it's easy to store the return value.

another problem to consider is yout STx registers usage. After return, value must be pushed on stack, and all things that were there before should remain. So when before calling there was:
ST0=0.0
ST1=-5.0e3
after return it should be
ST0=return value
ST1=0.0
ST2=-5.0e3

It would be best if you could preserve all 6 ST registers somehow. If not, at least mention in documentation how many ST registers are used internally by function.
Post 24 Mar 2007, 11:55
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav 24 Mar 2007, 12:23
try to port FPULIB from masm package
Post 24 Mar 2007, 12:23
View user's profile Send private message Reply with quote
ATV



Joined: 31 Aug 2004
Posts: 109
Location: Finland
ATV 26 Mar 2007, 12:18
Vid, here is two routines to start with. (without error checking)
Code:
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; ascii2float (buffer, number)
; param:  buffer -> Asciiz string
;         number -> pointer for qword number
; notes: number range is 1e-300 to 1e300
;        all number before and after dot '.' are added with st=st*10+new_number
;        when numbers end divide by 10 with count of numbers after dot
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
proc    ascii2float \
        buffer:DWORD,\
        number:DWORD

        push    eax ebx ecx edx esi
        mov     esi,[buffer]
        fninit
        fldz
        or      ecx,-1          ; digit count after '.' (-1 = none)
        xor     ebx,ebx         ; ebx: bit0 = mantissa sign , bit1 = exp sign
        xor     edx,edx         ; exponent

    .test_sign:
        cmp     byte [esi],'+'
        je      .sign_skip
        cmp     byte [esi],'-'
        jne     .new_char
        xor     ebx,1

    .sign_skip:
        inc     esi
        jmp     .test_sign

    .new_char:
        movzx   eax,byte [esi]
        cmp     al,'.'
        je      .separator
        cmp     al,','
        jne     .not_separator

    .separator:
        xor     ecx,ecx
        jmp     .next_number

    .not_separator:
        cmp     al,'e'
        je      .exponent
        cmp     al,'E'
        je      .exponent
        sub     al,'0'
        cmp     al,9
        ja      .number_end
        push    eax
        fmul    [f10]
        fiadd   dword [esp]
        pop     eax
        or      ecx,ecx
        js      .next_number
        inc     ecx

    .next_number:
        inc     esi
        jmp     .new_char

    .exponent:
        inc     esi
        cmp     byte [esi],'+'
        je      .exponent
        cmp     byte [esi],'-'
        jne     .exp_char
        xor     ebx,2
        jmp     .exponent

    .exp_char:
        movzx   eax,byte [esi]
        sub     al,'0'
        cmp     al,9
        ja      .number_end
        imul    edx,10
        add     edx,eax
        inc     esi
        cmp     edx,30
        jb      .exp_char

    .number_end:
        cmp     ecx,1
        jl      .add_exp
        fdiv    [f10]
        dec     ecx
        jmp     .number_end

    .add_exp:
        test    edx,edx
        jz      .exp_ok
        dec     edx
        test    ebx,2
        jz      .exp_positive
        fdiv    [f10]
        jmp     .add_exp

    .exp_positive:
        fmul    [f10]
        jmp     .add_exp

    .exp_ok:
        test    ebx,1
        jz      .sign_ok
        fchs

    .sign_ok:
        mov     ebx,[number]
        fstp    qword [ebx]
        pop     esi edx ecx ebx eax
        ret
endp    

Code:
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; float2ascii (number, count, buffer)
; put float value ?.? into buffer
; param:  number -> pointer to qword number
;         count  -> count of digits to display after dot '.'
;         buffer -> buffer for Asciiz string
; notes: number range is 1e-300 to 1e300
;        if number is below 1e-15 or above 1e15 use exponent format
; ToDo: better rounding (display 1.2 not 1.199999...)
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
proc    float2ascii \
        number:DWORD,\
        count:DWORD,\
        buffer:DWORD

local   old_cw:WORD,\
        new_cw:WORD,\
        packed_BCD:TBYTE,\
        BCD_buffer[20]:BYTE

        push    eax ebx ecx edx esi edi
        mov     edi,[buffer]
        xor     edx,edx                 ; exponent
        fninit
        fstcw   [old_cw]
        mov     ax,[old_cw]
        or      ax,0000110000000000b    ; no fpu rounding
        mov     [new_cw],ax
        fldcw   [new_cw]
        mov     ebx,[number]
        fld     qword [ebx]
        ftst
        fstsw   ax
        sahf
        jp      .error
        je      .mantissa
        jnc     .positive
        fabs
        mov     byte [edi],'-'
        inc     edi

    .positive:
        fcom    [f1e_300]               ; test if too small
        fstsw   ax
        sahf
        jb      .mantissa
        fcom    [f1e_15]                ; test if too many zeros
        fstsw   ax
        sahf
        jb      .test1
        fcom    [f1e15]                 ; test if too many digits
        fstsw   ax
        sahf
        jb      .mantissa

    .test10:
        fcom    [f10]
        fstsw   ax
        sahf
        jb      .mantissa
        inc     edx
        fdiv    [f10]
        jmp     .test10

    .test1:
        fcom    [f1]
        fstsw   ax
        sahf
        jnb     .mantissa
        dec     edx
        fmul    [f10]
        jmp     .test1

    .error:
        mov     dword [edi],'ERRO'
        mov     word [edi+4],'R'
        add     edi,5
        jmp     .float_end

    .mantissa:
        lea     ebx,[packed_BCD]
        fld     st
        fbstp   [ebx]
        lea     esi,[BCD_buffer]
        mov     ecx,9                   ; 9 packed BCD numbers + sign byte

    .unpack_BCD:
        movzx   eax,byte [ebx]
        inc     ebx
        shl     eax,4
        shr     al,4
        mov     [esi],ax
        add     esi,2
        loop    .unpack_BCD
        lea     ecx,[BCD_buffer]        ; start of BCD buffer

    .skip_zero:
        dec     esi
        cmp     byte [esi],0
        jne     .number
        cmp     esi,ecx                 ; don't skip last 0
        ja      .skip_zero

    .number:
        mov     al,[esi]                ; convert byte -> ASCII
        dec     esi
        or      al,'0'
        mov     [edi],al
        inc     edi
        cmp     esi,ecx
        jae     .number
        mov     ecx,[count]             ; digit count after dot
        or      cl,cl
        je      .float_end
        cmp     cl,15                   ; if over 15 it must be error
        jb      .dot
        mov     cl,8                    ; use default 8 digits

    .dot:
        mov     byte [edi],'.'
        inc     edi

    .new_decimal:
        fld     st                      ; digit = (st-int(st))*10
        frndint
        fsubp                           ; use only decimal part
        fmul    [f10]                   ; get first digit after dot
        fist    dword [edi]             ; and save it
        or      byte [edi],'0'
        inc     edi
        dec     cl                      ; loop until all decimals are done
        jnz     .new_decimal

round_result = 0
if round_result = 1
        fmul    [f10]
        fist    dword [edi]
        cmp     byte [edi],5
        jb      .round_ok
        mov     ebx,edi
    .round_more:
        dec     ebx
        mov     al,[ebx]
        cmp     al,'0'
        jb      .round_ok
        cmp     al,'9'
        ja      .round_ok
        jb      .do_inc
        mov     byte [ebx],'0'
        jmp     .round_more
    .do_inc:
        inc     byte [ebx]
    .round_ok:
end if

    .exp_sign:
        mov     al,'+'
        or      edx,edx
        jz      .float_end
        jns     .exp_positive
        neg     edx
        mov     al,'-'

    .exp_positive:
        mov     byte [edi],'e'          ; put exponent: 'e+000'
        inc     edi
        mov     [edi],al
        inc     edi
        mov     eax,edx
        mov     ebx,10
        mov     ecx,2

    .exp_loop:
        xor     edx,edx
        div     ebx
        or      dl,'0'
        mov     [edi+ecx],dl
        dec     ecx
        jns     .exp_loop
        add     edi,3

    .float_end:
        fldcw   [old_cw]
        mov     byte [edi],0
        pop     edi esi edx ecx ebx eax
        ret
endp

; data
        f1              dq 1.0
        f10             dq 10.0
        f1e_300         dq 1e-300
        f1e15           dq 1e15
        f1e_15          dq 1e-15    
Post 26 Mar 2007, 12:18
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.