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
Rui,
SRC1_REAL OR SRC2_DMEM.
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.
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
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).
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
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.
Hi raymond,
Thank you so much.
I think, sometimes, my processor is not well.
Rui
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