The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: grubish on April 27, 2011, 07:55:41 PM

Title: Working With the FPU
Post by: grubish on April 27, 2011, 07:55:41 PM
Hey Everyone,
      I'm back again with one of my doubts that needs to be cleared. I been trying to work with floating point numbers for a while and get a feel of it. So long story short, I have decided to write a piece of code that will compare three variables and print the largest amongst them. I know it sounds easy! And I feel the same way too.

My question is - Should I take the user input in a QWORD, then invoke StrtoFloat. Then invoke FpuComp (see for the RETURN value in EAX) and logically  build the algorithm ? Or should i just take the user input in REAL8 datatypes, load the numbers in FPU and compare ?

Disclaimer - I'm not asking anyone to show me the code or even pseudo-code it for me. I just intend to know which one's the right way to go about it.

Thank you.
Title: Re: Working With the FPU
Post by: MichaelW on April 27, 2011, 08:10:27 PM
I think you would learn more if you used the FPU directly. If by user input you mean the user typing in a string that represents a floating-point value, you will need to convert the string to an appropriate number before you can load it into the FPU.
Title: Re: Working With the FPU
Post by: grubish on April 27, 2011, 08:41:57 PM
Yea, the user will type in the string from the standard input. So, I'm guessing the algorithm should be something like ...

1) user input and convert it to float
2) invoke FpuComp and pass the pointer of the converted value (Float) to the PROC and then check EAX for CMP_EQU or CMP_GREATER or CMP_LOWER

What're your thoughts on that ?
Title: Re: Working With the FPU
Post by: jj2007 on April 27, 2011, 09:15:59 PM
Whatever routine for conversion you use is not so important. You need to see with your own eyes what's happening in the FPU, and only Olly (http://www.ollydbg.de/version2.html) can show you that. Especially the barrel principle is difficult in the beginning - the FPU behaves a bit like the stack, but in a more complex way.

Here is a template for playing around...

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Download (http://www.masm32.com/board/index.php?topic=12460)
.data?
Num1   REAL10 ?
Num2   REAL10 ?
  Init
  .Repeat
   MovVal Num1, Input$("Type the first number and hit Enter:  ")
   MovVal Num2, Input$("Type the second number and hit Enter: ")
   Print "Your numbers are ", Str$(Num1), " and ", Str$(Num2), CrLf$
   ; int      ; activate to have a look at your numbers in Olly
   fld Num1
   fld Num2
   deb 4, "You can see them on the FPU", ST(0), ST(1)   ; debug macro for console mode
   fstp st
   fstp st
   Fcmp Num1, Num2
   .if Carry?
      Print Str$("Num1 at %f is lower than ", Num1), Str$(Num2), CrLf$
   .elseif Zero?
      Print "Numbers are equal", CrLf$
   .else
      Print Str$("Num1 at %f is higher than ", Num1), Str$(Num2), CrLf$
   .endif
   Inkey "Press y for another round", CrLf$, CrLf$
  .Until eax!="y"
  Exit
end start

Sample output:
Type the first number and hit Enter:  12.34
Type the second number and hit Enter: 12.45
Your numbers are 12.34000 and 12.45000

You can see them on the FPU
ST(0)           12.4500000000000000
ST(1)           12.3400000000000000
Num1 at 12.34000 is lower than 12.45000
Press y for another round
Title: Re: Working With the FPU
Post by: grubish on April 27, 2011, 10:32:51 PM
Okay, i took your idea and played around with it for a while. But I don't know how correct I'm.


.386
.model flat, stdcall
option casemap: none

include \masm32\include\kernel32.inc
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\Fpu.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\Fpu.lib

.data
msg db "Enter a Floating Point Number", 10, 13, 0
buff dw 10 DUP(?)
value dw 10 DUP(?)
result db "They are Equal", 10, 13, 0
notresult db "Not Equal",0
buff1 dw 10 DUP(?)
value1 dw 10 DUP(?)

.code

start:
invoke StdOut, addr msg
invoke StdIn, addr buff, 10

invoke StdOut, addr msg
invoke StdIn, addr buff1, 10

invoke StrToFloat, addr buff, addr value
invoke StrToFloat, addr buff1, addr value1

invoke FpuComp, addr value, addr value1, SRC1_REAL or SRC2_REAL
test EAX, CMP_EQU
jz equal

jmp notequal


equal:

invoke StdOut, addr result

notequal:
invoke StdOut, addr notresult


invoke ExitProcess, 0
end start


Well, I've a feeling I'm way off the mark, since no matter what number I input... it prints both "result" and "notresult".
Title: Re: Working With the FPU
Post by: jj2007 on April 27, 2011, 10:46:34 PM
test...
.if Zero?
   invoke StdOut, addr result
.else
   invoke StdOut, addr notresult
.endif
Title: Re: Working With the FPU
Post by: grubish on April 27, 2011, 11:04:23 PM
It works like a charm. It was suggested to me by MichaelW, that I should load the values into FPU. So i wrote another piece of code, using FPU.

.386
.model flat, stdcall
option casemap: none

include \masm32\include\kernel32.inc
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\Fpu.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\Fpu.lib

.data

val1 REAL8 12.10
val2 REAL8 20.11

.code
start:
finit
fld val1
fcom val2
fstsw EAX


invoke ExitProcess, 0
end start


Is that the way to do it ?
Title: Re: Working With the FPU
Post by: raymond on April 28, 2011, 03:28:12 AM
@grubish

I get the impression that you are using an older version of the Fpulib. If you wish to continue to use that older version, you must be aware that it accepts only extended double precision floats (80 bits, 10 bytes) as input for most functions. Then, you should also check what type of floats may be returned by funcions outside of the Fpulib, such as the StrToFloat from the m32lib. That one happens to return 64-bit floats.

The way you had your memory variables set up, The FpuComp function may have seemed to work OK but it certainly did not load the proper 80-bit floats as specified for comparison.

The latest Fpulib has expanded options for the data types which can be used with the lib functions. You can get the latest version v2.33 from:
http://www.ray.masmcode.com/fpu.html#fpulib

Be sure to read AND understand the help file as to the requirements of each function you intend to use.
Title: Re: Working With the FPU
Post by: grubish on April 28, 2011, 08:21:57 AM
Hey Raymond,
       Thanks for the heads up and the tips. Actually in the previous code where I use the FpuLib works okay ;but What I'm trying to wrap my head around is this. In this I take a input(DWORD) and convert it a REAL8 value. And I didn't thoroughly read the Fpulib, but the fld seems to convert the REAL4 or REAL8 values to REAL10 (80 bit) ones. Here's what I have so far ... I'd like your inputs on that matter. Thanks.


386
.model flat, stdcall
option casemap: none

include \masm32\include\kernel32.inc
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\Fpu.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\Fpu.lib

.data
msg db "Enter a floating point number", 10, 13, 0

crlf db 10, 13, 0
val1 REAL8 ?
var2 dw 10 DUP(?), 0
val3 REAL8 ?
var3 dw 10 DUP(?), 0
val2 REAL8 ?
var1 dw 10 DUP(?), 0


.code
start:

invoke StdOut, addr msg
invoke StdIn, addr var1, 10



invoke StdOut, addr msg
invoke StdIn, addr var2, 10

invoke StdOut, addr msg
invoke StdIn, addr var3, 10

invoke StdOut, addr crlf



finit

fild var1
fstp val1

fild var2
fstp val2

fild var3
fstp val3

fld val1
fcom val2
fstsw AX
fwait
sahf

ja one_greater
jb one_lower
jz onetwo_equal
               
                ......



It seems to be working fine for the most part except for some glitches. I'm trying to get a better solution.
Title: Re: Working With the FPU
Post by: jj2007 on April 28, 2011, 09:23:48 AM
You cannot fld a string onto the FPU. Some conversion is needed. Check the FPU lib for conversion, or use MasmBasic together with OllyDbg

MovVal Num1, Input$("Type the first number and hit Enter:  ")
int 3 ; Olly will stop here
fld Num1 ; see what happens
Title: Re: Working With the FPU
Post by: grubish on April 28, 2011, 09:30:11 AM
 I have used fld on var1 and var1 is a REAL8. And i have converted it using


fild var1
fstp val1



So here's the thing, I can print the lowest floating point number, but when say (a, b and c are three floating point number) and when ( a==b | b==c|c==a) and lowest, and i try to print those two values, i get nothing. It's really weird.
Title: Re: Working With the FPU
Post by: jj2007 on April 28, 2011, 09:33:36 AM
Quote from: grubish on April 28, 2011, 09:30:11 AM
I have used fld on var1 and var1 is a REAL8. And i have converted it

Njet. You haven't converted anything. You are passing a string, not a numeric value. Of course, the FPU will try to interpret the string as a REAL4, but you get rubbish. USE OLLY.

invoke StdIn, addr var1, 10  ; var1 contains a string
Title: Re: Working With the FPU
Post by: grubish on April 28, 2011, 09:38:59 AM
ah okay, got you. So, can I use StrToFloat and then use FLD on the converted value ?
Title: Re: Working With the FPU
Post by: bomz on April 28, 2011, 09:42:07 AM
Quote
--------------------------------
AReg            WORD64 ?
CReg            dt ?
--------------------------------
finit
fild AReg
fbstp CReg
--------------------------------
Thats work - convert to compress 10
Title: Re: Working With the FPU
Post by: jj2007 on April 28, 2011, 09:53:28 AM
Quote from: grubish on April 28, 2011, 09:38:59 AM
can I use StrToFloat and then use FLD on the converted value ?

Exactly. Alternatively, use MovVal as shown in reply #3.

And it would be even better if you learned how to use Olly, otherwise you will continue playing around without understanding anything.
Title: Re: Working With the FPU
Post by: grubish on April 28, 2011, 10:02:40 AM
Just found some tutorials on ollydbg and since it has been mentioned a couple of times today, I'll make an effort to learn 'how to use it'. I mean I sometimes write code in emu8086 and it gives a very clear view of the inner workings and what I'm wrong about.
Title: Re: Working With the FPU
Post by: bomz on April 28, 2011, 10:18:24 AM
Never use fwait, all work Ok. May be on my computer only
Title: Re: Working With the FPU
Post by: raymond on April 28, 2011, 08:29:13 PM
@grubish

Trying to use the FPU without any of the basic knowledge of how it works will only bring you headaches. Spending a little time and effort on learning the basics would be a great investment. Have at least a glance at the first 2 chapters of the following FPU tutorial:
http://www.ray.masmcode.com/fpu.html