Hello everybody,

The following code multiplies two predefined numbers:

Operand1 REAL8 32.0

Operand2 REAL8 8.0

Result dq 0

finit

fld Operand1

fld Operand2

fmul st(0),st(1)

fstp Result

invoke FloatToStr,Result,offset TempBuf

How is it possible to load numbers into Operand1 and Operand2 variables?

best regards,

czDrillard

The following code multiplies two predefined numbers:

Operand1 REAL8 32.0

Operand2 REAL8 8.0

Result dq 0

finit

fld Operand1

fld Operand2

fmul st(0),st(1)

fstp Result

invoke FloatToStr,Result,offset TempBuf

How is it possible to load numbers into Operand1 and Operand2 variables?

best regards,

czDrillard

via stack?

**fld**means that the contents of memory is loaded to FPU register (specifically,

**st(0)**), not the reverse.

...and

It should be converted to the corresponding FP format depending on the size of the variable. So the following:

will store the contents of

**fstp**stores the contents of**st(0)**into the variable and pops it from the FPU stack.It should be converted to the corresponding FP format depending on the size of the variable. So the following:

`fstp Operand1`

will store the contents of

**st(0)**as a REAL8.How is it possible to load numbers into Operand1 and Operand2 variables?

There are 3 ways to do it.
The first one is to initialize the variable in the .data section as you seem to already know how.

The second way is to calculate values (such as the coordinates of the apex of a tetrahedra, or whatever) and store the results in the variables as you also seem to know how. (Integer values can simply be kept in integer variables and still be fully available for use in the FPU.)

The third way is to request information from the user. That information is usually recovered in the form of an alphanumeric string which must be converted to the proper binary format, either integer or floating point. You can either code that conversion yourself or (until you get more familiar with FPU instructions) use some library function, such as the FpuAtoFL in the fpu.lib which you can find at the end of the following thread:

http://www.asmcommunity.net/board/index.php?topic=9717&highlight=fpulib

You may also get some usefull information in the following tutorial:

http://www.masmforum.com/website/tutorials/fptute/index.html

Raymond

Hello everybody,

Thanks for all the replies. Raymond, thankyou for the excellent help file and the tutorials. I've been studying them for some time and found they remove

this dosen't work:

Operand1 REAL8 0.0

Operand2 dd 0

Result dq 0

finit

lea eax,Operand1

mov dword ptr ,32

fld dword ptr

mov Operand2,8

fmul Operand2

fstp Result

invoke FloatToStr,Result,offset TempBuf

this code results in 5.026912e-088 should be 256 ??

How to load two numbers generated at run time and multilply them together using the FPU?

Any help much appreciated,

best regards,

czDrillard

Thanks for all the replies. Raymond, thankyou for the excellent help file and the tutorials. I've been studying them for some time and found they remove

*some*of the mystery out of the FPU. :)this dosen't work:

Operand1 REAL8 0.0

Operand2 dd 0

Result dq 0

finit

lea eax,Operand1

mov dword ptr ,32

fld dword ptr

mov Operand2,8

fmul Operand2

fstp Result

invoke FloatToStr,Result,offset TempBuf

this code results in 5.026912e-088 should be 256 ??

How to load two numbers generated at run time and multilply them together using the FPU?

Any help much appreciated,

best regards,

czDrillard

You have to make the fpu to convert the integers into fp and vice versa.

At a first glance, i would do this:

Notice the "fild" to load an integer into a fp register.

Notice also the "fistp" to return it as an integer from a fp register.

If the variable Result have to be a quad word then use "fstp" (but the format will need to be converted because it will not be in decimal notation).

h.

At a first glance, i would do this:

```
```

Operand1 dd 0

Operand2 dd 0

Result dd 0

finit

lea eax,Operand1

mov dword ptr [eax],32

fild dword ptr [eax]

lea eax,Operand2

mov dword ptr [eax],8

fild dword ptr [eax]

fmul st(0),st(1)

fistp Result

Notice the "fild" to load an integer into a fp register.

Notice also the "fistp" to return it as an integer from a fp register.

If the variable Result have to be a quad word then use "fstp" (but the format will need to be converted because it will not be in decimal notation).

h.

Thanks hitchhikr

That works but I need to use real numbers for variables. I will be dividing two integers then multiplying the result. The result will usually be a decimal fraction.

Btw, I'm doing all this to scale my dialog boxes and re-set some of the controls.

best regards,

czDrillard

That works but I need to use real numbers for variables. I will be dividing two integers then multiplying the result. The result will usually be a decimal fraction.

Btw, I'm doing all this to scale my dialog boxes and re-set some of the controls.

best regards,

czDrillard

Just remember that you need to use fistp to store/convert a fp value into an integer (and fild to do the other way round).

also "frndint" can be of some use to convert fp -> integer.

h.

also "frndint" can be of some use to convert fp -> integer.

h.

Btw, I'm doing all this to scale my dialog boxes and re-set some of the controls

For this type of usage, you don't need the higher precision of REAL8 numbers. The REAL4 has sufficient precision and sufficient range.
Assuming the 1st division of 2 integers (in EAX and EDX for this example) is to get the ratio which will be used to scale several other dimensions,

```
.data?
```

ratio REAL4 0

integer1 dd 0

result dd 0

.code

mov integer1,eax

fild integer1

mov integer1,edx

fidiv integer1

fstp ratio ;store the ratio and free the FPU

......

;get an integer to be scaled into EAX

mov integer1,eax ;store it in a memory variable

fild integer1 ;load it to the FPU from memory

fmul ratio

fistp result ;store the scaled dimension and free the FPU

The latter result is a

**rounded integer**as you would require for a scaled dimension. A result with a fractional portion would not be of much use in this context.

Raymond

Thanks Raymond, I am using very similar code other than Result must be dq type data in order to use the following code:

invoke FloatToStr,Result,offset TempBuf

xor eax,eax

invoke atodw,ADDR TempBuf

mov x,eax

Then I pass x to the CreateWindowEx function to set x location.

best regards,

czDrillard

invoke FloatToStr,Result,offset TempBuf

xor eax,eax

invoke atodw,ADDR TempBuf

mov x,eax

Then I pass x to the CreateWindowEx function to set x location.

best regards,

czDrillard

Unless you MUST have the result as an ascii string for some other purpose, you are taking some un-necessary high risk using that quoted route.

1st, if I remember correctly, the FloatToStr funjction returns a string with some fractional decimal digits. You are not getting a rounded integer string.

2nd, again if I remember correctly, the atodw function does not check the string for errors. One version I have seen treats all characters as numerical digits up to the terminating 0! The returned result may be useless.

My suggested code would place your required result directly into your "x" variable. NO RISK and rounded.

Raymond

1st, if I remember correctly, the FloatToStr funjction returns a string with some fractional decimal digits. You are not getting a rounded integer string.

2nd, again if I remember correctly, the atodw function does not check the string for errors. One version I have seen treats all characters as numerical digits up to the terminating 0! The returned result may be useless.

My suggested code would place your required result directly into your "x" variable. NO RISK and rounded.

Raymond

Raymond, I have changed my code to match yours and not using FloatToStr function.

Btw, I was calling frndint before popping stack to ensure no decimals...it all seemed to work fine but why have all the unecessary overhead:grin:

Thankyou very much for your time and help.

best regards,

czDrillard

Btw, I was calling frndint before popping stack to ensure no decimals...it all seemed to work fine but why have all the unecessary overhead:grin:

Thankyou very much for your time and help.

best regards,

czDrillard

czDrillard

For your particular application, you could also look at using fixed point maths and do all the computation with the CPU instead of the FPU.

This involves using part of the dword for the integer portion and the remaining part for the fraction, the size of each being based on current needs. For example, the H.O. 16 bits of a dword for the integer portion allow a range of +/- 64k for unsigned values, and the remaining L.O. 16 bits for the fraction would be equivalent to approx. 5 decimal places.

Again assuming you don't need to convert the scaled value to ascii with a decimal portion for some other purpose, the code could look like the following. It assumes that the two values required to compute the scaling ratio are already in EAX and ECX.

The beauty of assembler!!!:tongue:

Raymond

For your particular application, you could also look at using fixed point maths and do all the computation with the CPU instead of the FPU.

This involves using part of the dword for the integer portion and the remaining part for the fraction, the size of each being based on current needs. For example, the H.O. 16 bits of a dword for the integer portion allow a range of +/- 64k for unsigned values, and the remaining L.O. 16 bits for the fraction would be equivalent to approx. 5 decimal places.

Again assuming you don't need to convert the scaled value to ascii with a decimal portion for some other purpose, the code could look like the following. It assumes that the two values required to compute the scaling ratio are already in EAX and ECX.

```
.data
```

ratio dd 0

x dd 0

.code

shl eax,16 ;shift numerator to H.O. 16 bits

cdq ;clears EDX for the division

div ecx ;result in EAX with a 16-bit fraction

mov ratio,eax

....

mov eax,[I]value_to_be_scaled[/I]

mul ratio

shr eax,16 ;get rid of the fraction

jnc @F

inc eax ;round it if fraction >= 1/2

@@:

mov x,eax

The beauty of assembler!!!:tongue:

Raymond

I'll file that away for future reference. An elegant piece of code Raymond, serving as a reminder of the versatility of assembler.

best regards,

czDrillard

best regards,

czDrillard