News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

fpuFLtoA problem

Started by RuiLoureiro, February 03, 2008, 08:07:41 PM

Previous topic - Next topic

RuiLoureiro

Hi
           I have a problem with  FpuFLtoA. I am not understanding how it works.
           I have the number -7.0. I want 3 decimal places. When i call CvRealString
           i get -7.000000000000000 in StrValorX. Is this correct ? It works this way ?

           Thank you           
           
       
.data
ValorX          REAL10 -7.0

                dd 35
                dd 0
StrValorX       db 35 dup (?)

.code
CvRealString    proc               
                LOCAL   NUMDEC:DWORD
                push    esi
                ;
                xor     eax, eax
                mov     al, 3             ; number of decimal digits
                mov     ah, 5             ; number of char before decimal point

                mov     NUMDEC, eax
                ;
                lea     ebx, NUMDEC                                 
                mov     ecx, offset ValorX               
                mov     esi, offset StrValorX
                invoke  FpuFLtoA, ecx, ebx, esi, SRC1_REAL
                ;
                ;call    CvDosRcl
                ;                                             
                pop     esi
                ret
CvRealString    endp

       
RuiLoureiro

GregL

Rui,

SRC1_REAL OR SRC2_DMEM.


raymond

Or, if you don't want to reuse what you store in NUMDEC within the same call to the procedure,
invoke  FpuFLtoA, ecx, eax, esi, SRC1_REAL or SRC2_DIMM

And you don't have to tie up registers with addresses of variables, such as with
invoke  FpuFLtoA, ADDR ValorX, ADDR NUMDEC, ADDR StrValorX, SRC1_REAL or SRC2_DMEM

What happened with your code was that you did not identify the second parameter as being the content of a memory variable. The function then treated that parameter as an immediate value (i.e. the content of EBX). If the BL register was greater than 15, it used 15 as the number of decimals required (which you got). It also used the value in the BH register to pad the front end of the ASCII string with space characters up to a maximum of 17 characters before the decimal point.

So, to answer your questions Is this correct ? It works this way ?, YES it does work this way.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

RuiLoureiro

Hi Greg,
           Thanks
           
Hi Raymond,
           How are you ? Thank you. It works           

           To test my knowledge of FPU now, a wrote this code below.
           The first time it runs OK with correct results. But now it gives me an error.
           It exits with eax = 0.
           Can you help me ? Whats wrong. I am not seeing where is the problem
           
           Thanks for your help
                       
       
.data
;
; All numbers are real numbers
; ----------------------------
NumberA         REAL10   1.0           
NumberB         REAL10  -1.0           
NumberC         REAL10 -12.0           
;............................
Number4         REAL10 -4.0
;............................
SolutionX0      REAL10 ?           
SolutionX1      REAL10 ?           

.code
; output:
;
;           EAX = 2   OK
;               = 1   b^2 - 4ac < 0
;               = 0   ERROR
;
PrcRoots        proc

                finit
                ;
                fld     NumberA             ; reg 7                 
                fld     st(0)               ; reg 6
                fadd                        ; reg 7                = 2a
               
                fld     NumberB             ; reg 6                 
                fchs                        ; reg 6                 - b
               
                fld     st(0)               ; reg 5                 - b
                ;
                fld     Number4             ; reg 4                 ; -4.0
                fld     NumberA             ; reg 3
                fld     NumberC             ; reg 2
                ;
                fmul                        ; reg 3                  ac
                fmul                        ; reg 4                 = -4ac

                fld     NumberB             ; reg 3
                fld     st(0)               ; reg 2
                fmul                        ; reg 3                 = b^2

                fadd                        ; reg 4  st(0) now      = b^2 - 4ac

                ;
                ftst           
                fwait                   
                ;
                fstsw   ax

                sahf
                jpe     _error               
                jae     _ePrcRoots
                ;
                ; b^2 - 4ac < 0
                ; -------------
                mov     eax, 1
                ret
                ;
                ; error
                ; -----
_error:         mov     eax, 0
                ret
                ;
                ; b^2 - 4ac >= 0
                ;
_ePrcRoots:     fsqrt                       ; reg 4   
                fld      st(0)              ; reg 3    st(0) now

                faddp    st(2), st(0)       ; reg 5                 = -b + sqrt
                fsubp    st(2), st(0)       ; reg 6                 ; -b - sqrt
                ;
                fdiv     st(0), st(2)
                fstp     SolutionX0       
                ;
                fdiv     st(0), st(1)
                fstp     SolutionX1         ; reg 7    st(0) now

                fstp     st(0)              ; clear
                ;
                mov      eax, 2
                ret
PrcRoots        endp

       
RuiLoureiro

raymond

QuoteThe first time it runs OK with correct results.

As far as I can tell, your code should produce the correct result (even though your code could be slightly simplified). If you continue using that same code with the identical data, it should continue giving you the same result without generating any error.

QuoteBut now it gives me an error.

Could you elaborate a bit more on that "now". For example, did you try using the code with different data? If yes, what was the source of that data (with all pertinent details)? Can you replicate the error you are getting? Have you tried stepping through your code with a debugger if you can replicate the error?

(The only way I can see your code generating an error detected by the ftst instruction is to use it with some source data considered as NaN).
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

RuiLoureiro

Hi raymond,
                Thanks, it is working now.

Quoteeven though your code could be slightly simplified.

            How ? Could you help me ?
...............................................................           
            But what happen ?
           
             1. i used the same data in all tests;
             
             2. i replaced Number4 = 4.0 and
                                             fld     Number4
                                             fchs
                               by
                                             Number4 = -4.0 and
                                             fld     Number4
                And after this i got error;
               
             3. I used PEEK to see the registers after ftst:

                                ftst           
                                fwait                   
                                ;
                                fstsw   ax
                                call     regs
                               
                and i got: AX= 4541h -> invalid operation, C3=C2=C0=1 -> uncomparable

             4. I decided to copy that proc to another and call another name and change
               
                                ftst           
                                ;
                                fstsw   ax
                                fwait                                                   

             5. Now, it is working and the code that below. Could you help me how to simplify this ?
                Thank you


; Input:
;           .data
;                   NumberA     REAL10 ?
;                   NumberB     REAL10 ?
;                   NumberC     REAL10 ?
;                   Number4     REAL10 -4.0
;.........................................
;                   RootX0      REAL10 ?           
;                   RootX1      REAL10 ?     
;                   ImaginarX0  REAL10 ?         
;                   ImaginarX1  REAL10 ?           
;                                                    complex: RootX0+i ImaginarX0,
;                                                             RootX1+i ImaginarX1
;                                                    where ImaginarX1 = - ImaginarX0
; Output:
;           EAX = 0  -> error
;               = 1  -> real roots
;               = 2  -> complex roots
;
;            The roots are in global variables RootX0, RootX1
;            and ImaginarX0, ImaginarX1
;
; usage:
;           Define NumberA, NumberB and NumberC ( REAL10 values )
;           If NumberA not equal 0,
;                                   call    CalcRoots
;                                   cmp     eax, 0
;                                   jne     @F
;                                   ; error
;
;                           @@:     cmp     eax, 1
;                                   jne     @F
;                                   ; real roots
;                   
;                           @@:     ; complex roots
;
CalcRoots       proc   
                ;
                finit
                ;
                fld     NumberA             ; reg 7                 
                fld     st(0)               ; reg 6
                fadd                        ; reg 7                = 2a
               
                fld     NumberB             ; reg 6                 
                fchs                        ; reg 6                 - b
               
                fld     st(0)               ; reg 5                 - b
                ;
                fld     Number4             ; reg 4                 ; -4.0
                fld     NumberA             ; reg 3
                fld     NumberC             ; reg 2
                ;
                fmul                        ; reg 3                  ac
                fmul                        ; reg 4                 = -4ac

                fld     NumberB             ; reg 3
                fld     st(0)               ; reg 2
                fmul                        ; reg 3                 = b^2

                fadd                        ; reg 4  st(0) now      = b^2 - 4ac

                ;
                ftst                        ; compare st(0) against 0.0           
                fstsw   ax
                fwait                   

                sahf
                jpe     _rCalcRoots         ; error               
                jae     _eCalcRoots         ; positive or 0
                ;
                ; b^2 - 4ac < 0
                ; -------------
               
                fchs                        ; reg 4               
                fsqrt                       ; reg 4    st(1) after fld
                fld      st(0)              ; reg 3    st(0)
                ;
                fchs               
                fdiv     st(0), st(4)
                fstp     ImaginarX0 
                ;
                fdiv     st(0), st(3)
                fstp     ImaginarX1
                ;
                fdiv     st(0), st(2)
                fstp     RootX0       
                ;
                fdiv     st(0), st(1)
                fstp     RootX1

                fstp     st(0)              ; clear
                ;
                mov       eax, 2
                ret
                ;
_rCalcRoots:    mov     eax, 0
                ret
                ;
                ; b^2 - 4ac >= 0
                ;
_eCalcRoots:    fsqrt                       ; reg 4    st(1) after fld
                fld      st(0)              ; reg 3    st(0)

                faddp    st(2), st(0)       ; reg 5                 = -b + sqrt
                fsubp    st(2), st(0)       ; reg 6                 ; -b - sqrt
                ;
                fdiv     st(0), st(2)
                fstp     RootX0       
                ;
                fdiv     st(0), st(1)
                fstp     RootX1

                fstp     st(0)              ; clear

                mov       eax, 1
                ret
CalcRoots       endp

     

RuiLoureiro       


raymond

Here are some simplifications.

                fld     NumberA             ; reg 7                 
                fld     st(0)               ; reg 6
                fadd                        ; reg 7                = 2a

There's no need to load a copy of the top register to add it to itself, i.e.
                fld     NumberA             ; reg 7                 
                fadd    st,st                ; reg 7                = 2a


You have already used the fact that adding a value to itself is faster than multiplying it by 2. You can do the same for other multiples of 2, such as:
                fld     NumberA             ; reg 4
                fld     NumberC             ; reg 3
                ;
                fmul                        ; reg 4                  ac
                fadd    st,st               ;reg 4                  2ac
                fadd    st,st               ;reg 4                  4ac
                fchs                        ;reg 4                  -4ac


Same as for addition, there's no need to load a copy of the top register to multiply it by itself, i.e.
                fld     NumberB             ; reg 3
                fmul    st,st               ; reg 3                 = b^2


                ; b^2 - 4ac < 0
                ; -------------
               
                fchs                        ; reg 4               
                fsqrt                       ; reg 4    st(1) after fld
                fld      st(0)              ; reg 3    st(0)
                ;
                fchs               
                fdiv     st(0), st(4)
                fstp     ImaginarX0 
                ;
                fdiv     st(0), st(3)
                fstp     ImaginarX1
                ;
                fdiv     st(0), st(2)
                fstp     RootX0       
                ;
                fdiv     st(0), st(1)
                fstp     RootX1

In the above, you are dividing the same numbers twice. Do the division only once, make a copy, change the sign of one and store them.
                ; b^2 - 4ac < 0
                ; -------------
               
                fchs                        ; reg 4               
                fsqrt                       ; reg 4
                fdiv     st(0), st(3)
                fld      st(0)              ; reg 3    st(0)
                fchs               
                fstp     ImaginarX0 
                fstp     ImaginarX1
                ;
                fstp     st                ; get rid of one of the -b
                ;
                fdiv     st(0), st(1)
                fld      st
                fstp     RootX0               
                fstp     RootX1


Quote            2. i replaced Number4 = 4.0 and
                                             fld     Number4
                                             fchs
                               by
                                             Number4 = -4.0 and
                                             fld     Number4
                And after this i got error;

I can't understand why that change should have resulted in an error.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

RuiLoureiro

Hi raymond,
                 Thank you so much.

                  I think, sometimes, my processor is not well.

Rui

RuiLoureiro

#8
Quote from: raymond on February 05, 2008, 08:26:32 PM
                fld      st(0)              ; reg 3    st(0)
                fchs               
                fstp     ImaginarX0 
                fstp     ImaginarX1
                ;
                fstp     st                ; get rid of one of the -b
              I think you want write

                fld      st(0)              ; reg 3    st(0)
                fstp     ImaginarX0
                fchs   
                fstp     ImaginarX1
                ;
                fstp     st                ; get rid of one of the -b


Here the complete code

;           .data
;                   NumberA     REAL10 ?
;                   NumberB     REAL10 ?
;                   NumberC     REAL10 ?
;.........................................
;                   RootX0      REAL10 ?           
;                   RootX1      REAL10 ?     
;                   ImaginarX0  REAL10 ?         
;                   ImaginarX1  REAL10 ?           
;                                    complex: RootX0+i ImaginarX0,
;                                             RootX1+i ImaginarX1
;                                    where ImaginarX1 = - ImaginarX0
; Output:
;           EAX = 0  -> error
;               = 1  -> real roots
;               = 2  -> complex roots
;
;            The roots are in global variables RootX0, RootX1
;            and ImaginarX0, ImaginarX1
;
; usage:
;           Define NumberA, NumberB and NumberC ( REAL10 values )
;           For integer values, replace fld by fild inside CalcRoots
;           If NumberA not equal 0,
;                                   call    CalcRoots
;                                   cmp     eax, 0
;                                   jne     @F
;                                   ; error
;
;                           @@:     cmp     eax, 1
;                                   jne     @F
;                                   ; real roots
;                   
;                           @@:     ; complex roots
;
CalcRoots       proc   
                ;
                finit
                ;
                fld     NumberA             ; reg 7
                fadd    st,st               ; reg 7                = 2a
               
                fld     NumberB             ; reg 6                 
                fchs                        ; reg 6                 - b
               
                fld     st(0)               ; reg 5                 - b
                ;
                fld     NumberA             ; reg 4
                fld     NumberC             ; reg 3
                ;
                fmul                        ; reg 4                  ac
                ;
                fadd    st,st               ; reg 4                  2ac
                fadd    st,st               ; reg 4                  4ac
                fchs                        ; reg 4                 -4ac

                fld     NumberB             ; reg 3
                fmul    st,st               ; reg 3                 = b^2

                fadd                        ; reg 4  st(0) now      = b^2 - 4ac
                ;
                ftst                        ; compare st(0) with 0.0           
                ;
                fstsw   ax
                fwait                   
                sahf
                jpe     _rCalcRoots         ; error               
                jae     _eCalcRoots         ; positive or 0
                ;
                ; b^2 - 4ac < 0
                ; -------------
                fchs                        ; reg 4               
                fsqrt                       ; reg 4
                fdiv     st(0), st(3)
                fld      st(0)              ; reg 3    st(0)
                ;
                fstp     ImaginarX0         ; reg 4
                fchs                               
                fstp     ImaginarX1         ; reg 5
                ;
                fstp     st                 ; reg 6 get rid of one of the -b
                ;
                fdiv     st(0), st(1)       ; reg 6
                fld      st(0)              ; reg 5
                fstp     RootX0             ; reg 6   
                fstp     RootX1             ; reg 7

                fstp     st(0)              ; store it to itsef and pop -> clear stack
                ;
                mov       eax, 2
                ret
                ;
_rCalcRoots:    mov     eax, 0
                ret
                ;
                ; b^2 - 4ac >= 0
                ;
_eCalcRoots:    fsqrt                       ; reg 4    ST(1)
                fld      st(0)              ; reg 3    ST(0)

                faddp    st(2), st(0)       ; reg 5                 = -b + sqrt
                fsubp    st(2), st(0)       ; reg 6                 ; -b - sqrt
                ;
                fdiv     st(0), st(2)
                fstp     RootX0       
                ;
                fdiv     st(0), st(1)
                fstp     RootX1

                fstp     st(0)              ; clear

                mov       eax, 1
                ret
CalcRoots       endp


RuiLoureiro