Author Topic: A question on FPU  (Read 3800 times)

clamicun

  • Member
  • **
  • Posts: 240
Re: A question on FPU
« Reply #15 on: February 09, 2016, 05:39:32 AM »
Hi HSE,

" fn crt_sprintf, addr endvalue, "%lf", FPU_calc..."

ok. but as I said...
Seeing it is good, but I nedd it for further use.
Thank you

clamicun

  • Member
  • **
  • Posts: 240
Re: A question on FPU
« Reply #16 on: February 09, 2016, 05:51:14 AM »
jj,

"I took a look. Resembles my Float2Asc routine - 500+ lines of scarcely commented code ::)"

That is what I meant ..
I do not understand it entirely (lots of code for little output).

Let esi=Str$("%4f",FPU_calc)
If esi is a string...
well I find out

...

HSE

  • Member
  • ****
  • Posts: 533
  • <AMD>< 7-32>
Re: A question on FPU
« Reply #17 on: February 09, 2016, 05:53:12 AM »
but I need the "endvalue".

Have you tested the function in your code?

jj2007

  • Member
  • *****
  • Posts: 7559
  • Assembler is fun ;-)
    • MasmBasic
Re: A question on FPU
« Reply #18 on: February 09, 2016, 06:21:35 AM »
Let esi=Str$("%4f",FPU_calc)
If esi is a string...

In C/C++ and assembler, a string is technically speaking a pointer to an area of memory that is delimited by a zero byte (or word in case of Unicode). You can use a register like esi, edi, ebx and ecx if you want smaller code, but Let my$=Str$(123) is valid as well, if my$ has been declared either in the .data? section or via SetGlobals.

On a very technical note,
Code: [Select]
Let my$="Hello"
Let my$=my$+" world"
is possible in MasmBasic. When my$ is assigned in the second line, the old my$ gets HeapFree'd after the new one was created. The same applies to esi, edi, ebx and ecx, but attention: If they pointed to something else before the first assignment, the heap might not agree with what you were doing. No such risk for a global variable like my$, of course, and no problem for arrays like x$(0). If you really want to use registers, the correct way is as follows:
Code: [Select]
xor esi, esi   ; make sure it doesn't point to the heap
Let esi="Hello"
Let esi=esi+" world"
PrintLine esi  ; do something useful
Clr$ esi   ; release the memory (->HeapFree)

clamicun

  • Member
  • **
  • Posts: 240
Re: A question on FPU
« Reply #19 on: February 09, 2016, 09:19:47 AM »
"Problem" resolved

MasmBasics...
fstp FPU_calculation
Let esi=Str$("%4f",FPU_calculation)
INVOKE lstrcpy,offset where_it_should_be,esi  ;for further use

Relatively small code  - using MasmBasics  "str$ MACRO" 

Nothing against the code of "RuiLoureiro" ,but...

as always - Thanks a lot jj
Mic

P.S.
One of these days I am going to understand "MasmBasics"




raymond

  • Member
  • **
  • Posts: 172
    • Raymond's page
Re: A question on FPU
« Reply #20 on: February 09, 2016, 10:03:07 AM »
clamicum

Quote
INVOKE crt_atof,offset startvalue
INVOKE crt_atof,offset value1
fadd st(0),st(1)                 ; add ST(0)+ST(1)

I don't know how the crt_atof works but I would suspect that it converts the input string
- with a clean FPU after saving all current FPU registers,
- saving its converted result in local memory,
- restoring the saved FPU registers,
- and finally loading the saved result onto the FPU.

The detail for which I have no information is if it blindly frees the st(7) register (which could still contain valuable data) before loading the saved result on the FPU. If not, you would have been lucky that your test included no more than 8 input strings; otherwise, your final output value would have been TRASH.

Maybe you should have a look at the FPU tutorial at http://www.ray.masmcode.com/fpu.html, which you can read on-line or download its content.
Trying to program the FPU without sufficient knowledge of its various pitfalls can only lead to a lot of frustration.

You also seemed curious about how the Convert8DR (or Float2Asc) routines worked. I don't know how those arrive at the intended result but, if you have the MASM32 package, the source code for the FpuFLtoA function from the fpulib library is well commented. Although it contains almost 500 lines, the first 195 lines are the overhead to verify the source and validity of the input. You can then easily follow the logic used for the conversion and eventual display according to user preferences.
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com/

jj2007

  • Member
  • *****
  • Posts: 7559
  • Assembler is fun ;-)
    • MasmBasic
Re: A question on FPU
« Reply #21 on: February 09, 2016, 10:59:02 AM »
The detail for which I have no information is if it blindly frees the st(7) register (which could still contain valuable data) before loading the saved result on the FPU. If not, you would have been lucky that your test included no more than 8 input strings; otherwise, your final output value would have been TRASH.

That is indeed a problem with this code:
INVOKE crt_atof,offset startvalue
INVOKE crt_atof,offset value1
fadd st(0),st(1)                 ; add ST(0)+ST(1)

INVOKE crt_atof,offset value2
fadd st(0),st(1)                

INVOKE crt_atof,offset value3
fadd st(0),st(1)             

INVOKE crt_atof,offset value4
fadd st(0),st(1)   
             
INVOKE crt_atof,offset value5
fadd st(0),st(1)

fstp FPU_calc         ;Store real number and pop ST(0)

There are three important mnemonics related to adding ST0 and ST1:
  fadd st(0), st(1)   ; adds st1 to st0, st1 remains valid   
  faddp st(1), st(0)   ; adds st1 to st0, st1 becomes empty
  fadd         ; identical to faddp st(1), st(0)

The version you used does not empty ST(1). So when you call crt_atof eight times, the FPU is full, and that will produce a bad result. You need to use the simple fadd instead. The best option: launch Olly and have a look.

@Ray: If the FPU is full, crt_atof produces a NAN. At least one ffree ST(7) is needed.
In contrast, MovVal ST(0), Chr$("123.456") will handle the ffree, but ST 5..7 will be trashed (which could be a problem under completely unrealistic assumptions; and before you kill me for that: a simple MsgBox also trashes two FPU regs, while many API calls trash several xmm regs without asking you for your permission 8))

clamicun

  • Member
  • **
  • Posts: 240
Re: A question on FPU
« Reply #22 on: February 09, 2016, 11:24:19 AM »
Maybe you should have a look at the FPU tutorial at http://www.ray.masmcode.com/fpu.html...
That is where learned the bit I know.

I do use  the proc 5 times (maximum) - there are 5 vars "value" only
and everytime the proc starts with

FINIT  ; It is good programming practice to take the precaution of initializing FPU before starting any computation
FFREE st(0)

Is that ok. ?

jj2007

  • Member
  • *****
  • Posts: 7559
  • Assembler is fun ;-)
    • MasmBasic
Re: A question on FPU
« Reply #23 on: February 09, 2016, 11:32:31 AM »
FINIT  ; It is good programming practice to take the precaution of initializing FPU before starting any computation
FFREE st(0)

Is that ok. ?

MB's Init does the finit once (it is a slow instruction). It does not hurt to do it again, but avoid using finit in a tight loop.
Re ffree st(0): Read Ray's tute, the "revolver" part. What you really need is to free the last register, i.e. ffree st(7), in order to allow st(0) to load a new value. Example, assuming a "full" fpu:
FpuFill  ; for testing, fill the FPU with 1001 ... 1008
ffree st(7)  ; discard the last value
fldz  ; load zero
ffree st(7)  ; discard the last value
fldpi  ; load PI
ffree st(7)  ; discard the last value
fld1  ; load 1
You have now
ST(0)=1
ST(1)=PI
ST(2)=0

Really, the best idea is to launch Olly and watch what happens. MB has the FpuFill macro, can be very handy for testing.

raymond

  • Member
  • **
  • Posts: 172
    • Raymond's page
Re: A question on FPU
« Reply #24 on: February 10, 2016, 04:36:57 AM »
Quote
FINIT  ; It is good programming practice to take the precaution of initializing FPU before starting any computation
FFREE st(0)

Is that ok. ?

For the first line comment, the answer may be yes or no according to the description of the FINIT instruction in the tutorial.

As for the second line, also from the tutorial (Chap, 1),

Quote
When the FPU is initialized, all the compartments are empty

It is thus useless to free "any" FPU register immediately following the finit instruction. The result of the FFREE instruction is to empty the specified register.
Whenever you assume something, you risk being wrong half the time.
http://www.ray.masmcode.com/

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: A question on FPU
« Reply #25 on: February 10, 2016, 05:58:32 AM »
to execute FINIT prior to any calculation is craziness
FINIT is quite slow - i generally execute it once at the beginning of a program
then, i take care to keep track of register usage

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: A question on FPU
« Reply #26 on: February 15, 2016, 02:27:02 AM »
I don't know how the crt_atof works...

The older Microsoft PSDKs, this one , for example, included a large part of the source for the CRTL, and if I remember correctly, this included the source for the atof function and a "worker" function that it calls to do the actual conversion.
Well Microsoft, here’s another nice mess you’ve gotten us into.