News:

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

crt_printf doesn't print float ?

Started by cobold, October 08, 2007, 07:36:49 PM

Previous topic - Next topic

cobold

Hello,

this code:
    finit
    fld eins    ;defined dq 1.0
    fdiv freq 
    fwait
    fstp TimerRes defined dq 0.0
    invoke crt_printf, ADDR fmt1, TimerRes, 10    ; fmt1 =db "%.20Lf%c",0

produces as output:
1.#INF0000000000000000

What am I doing wrong? I would be very thankful for any help/comments.


rgds
cobold

Vortex

Hi cobold,

Welcome to the forum.

You would like to look at this thread :

How to display a floating point number by invoking crt_printf?

http://www.masm32.com/board/index.php?topic=7924.0

cobold

Quote from: Vortex on October 08, 2007, 07:53:05 PM
Hi cobold,

Welcome to the forum.

You would like to look at this thread :

How to display a floating point number by invoking crt_printf?

http://www.masm32.com/board/index.php?topic=7924.0

Many thanks for your reply, but the thread applies to data defined as dd, stating that crt_printf works with real8 only.
Originally I defined TimerRes as dq, so why bother converting it?
Anyway, when I define TimerRes as real8, it prints "1.#INF00." all the same.
The funny thing about this is the fact that it prints 64-bit integers correctly, even with real8-defined variables, but whenever
a format-string with "%f" is used, the output is "1.#INF00."

Do I use the wrong format-string?

Thks in advance.

rgds
cobold

GregL

cobold,

Your code works OK for me. It doesn't matter if you use %f or %lf in the format string. What is the value of freq? If it's zero then ...

btw, you don't need the fwait.



raymond

As Greg pointed out, dividing by 0 would produce the result you are obtaining. Either initialize your freq variable with an appropriate value in floating point format or make sure you fill that variable with an appropriate value before you use it for dividing. (Any non-initialized variable will initially contain a value of 0.)

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

cobold

Quote from: Greg on October 08, 2007, 09:57:42 PM
cobold,

Your code works OK for me. It doesn't matter if you use %f or %lf in the format string. What is the value of freq? If it's zero then ...

btw, you don't need the fwait.




First of all a big thank you for everybody who answered to my post.
My problem of understanding is that freq is not or cannot be zero, because I
invoke QueryPerformanceFrequency, ADDR freq
and
invoke crt_printf, ADDR fmt, freq, 10
shows freq = 3579545

I have the following data:
; -------------------------------------------------------------------------
freq            real8   0.0   
overhead     real8   0.0
TimerRes     real8   0.0
eins            real8   1.0 ; for fdiv
; -------------------------------------------------------------------------
Then I want to calculate TimerRes = 1 / freq and display the result, so the FPU should work with
1.0 / 3579545
and therefore display 2.793651148e -7 ??
; -------------------------------------------------------------------------
; calculate Timerresolution
;          TimerRes = 1 / freq
; -------------------------------------------------------------------------
    invoke QueryPerformanceFrequency, ADDR freq
    print NL ; NewLine (13,10)
    print "freq = "
    invoke crt_printf, ADDR fmt, freq, 10 ; shows freq = 3579545 - so it's not zero
    print NL
    print "TimerFrequency = "
    finit
    fld eins           ; Load 1.0 into the FPU
    fdiv freq         ; calculate 1.0 / freq
    fstp TimerRes ; store result to TimerRes
    invoke crt_printf, ADDR fmt1, TimerRes, 10  ;1.#INF00.

It gave me headaches for hours, but I'm too stupid to find out by myself what's wrong.
Any suggestions?

Thks in advance.

cobold

GregL

cobold,

The parameter to QueryPerformanceCounter is a (pointer to) LARGE_INTEGER, you can use a QWORD. Use fild to load the value of freq since it is an integer.


.DATA

    ;eins     REAL8 1.0
    TimerRes REAL8 0.0
    freq     QWORD 0
    fmt      BYTE  "%lu%c",0
    fmt1     BYTE  "%.20lf%c",0

.CODE

    invoke QueryPerformanceFrequency, ADDR freq
    print chr$(13,10)
    print "freq = "
    invoke crt_printf, ADDR fmt, freq, 10
    print chr$(13,10)
    print "TimerFrequency = "
    finit
    fld1 ;eins      ; Load 1.0 into the FPU
    fild freq
    fdiv          ; calculate 1.0 / freq
    fstp TimerRes ; store result to TimerRes
    invoke crt_printf, ADDR fmt1, TimerRes, 10



cobold

THANK YOU SOOOO MUCH !!!

Now I see the problem was that QueryPerformanceCounter gives back a LARGE INTEGER,
and I should have "informed" the FPU with "fild" that this value is integer instead of float.
Simply using fdiv freq, the FPU "thinks" freq is float8.

thks  a lot again

rgds
cobold


GregL

cobold,

You are welcome. Keep at it, MASM is a blast.

Cheers,

Greg


raymond

The assembler may not always differentiate between a REAL8 and a QWORD definition for variables. Your call to QueryPerformanceFrequency was thus using the address of a qword size memory variable and the result was correctly stored AS A 64-BIT INTEGER.

With your fdiv freq instruction, you were then instructing the FPU to treat the content of that 64-bit variable as a REAL8 value. As such, that value would be less than 10-308 and the result of the division would have returned the INFINITY code which was correctly displayed by the crt_printf function.

If you need to brush up on data types, you may want to look at Chap.2 in the following:
http://www.ray.masmcode.com/tutorial/index.html

As a side note, there is no need to have a memory variable for holding a value of 1.0 and later loading it from memory to the FPU.

fld1
fild freq
fdiv


Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com