Problem with print float number

Hello everyone,

I’m used KeSaveFloatingPointState and KeRestoreFloatingPointState to handle the floating arithmetic ,and I want to check the result , so I used vsprintf() to change it to string and used KdPrint() to print it , but the result is Garbled. any ideal?

Here is my pseudo code:

double a = 1.0;

status = KeSaveFloatingPointState(&saveData);
if (NT_SUCCESS(status))
{
vspfunc(“%f”,a);
KdPrint((“%s \n”,a));
KeRestoreFloatingPointState(&saveData);
}

int vspfunc(char *format, …)
{
va_list aptr;
int ret;

va_start(aptr, format);
ret = vsprintf(buffer, format, aptr);
va_end(aptr);

return(ret);
}

Thanks
M.M

This

double a = 1.0;

before saving FP state is incorrect since this can cause use of FP state without the save.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Thursday, December 27, 2012 4:15 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Problem with print float number

Hello everyone,

I’m used KeSaveFloatingPointState and KeRestoreFloatingPointState to handle the floating arithmetic ,and I want to check the result , so I used vsprintf() to change it to string and used KdPrint() to print it , but the result is Garbled. any ideal?

Here is my pseudo code:

double a = 1.0;

status = KeSaveFloatingPointState(&saveData);
if (NT_SUCCESS(status))
{
vspfunc(“%f”,a);
KdPrint((“%s \n”,a));
KeRestoreFloatingPointState(&saveData);
}

int vspfunc(char *format, …)
{
va_list aptr;
int ret;

va_start(aptr, format);
ret = vsprintf(buffer, format, aptr);
va_end(aptr);

return(ret);
}

Thanks
M.M


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:

Hello everyone,

I’m used KeSaveFloatingPointState and KeRestoreFloatingPointState to handle the floating arithmetic ,and I want to check the result , so I used vsprintf() to change it to string and used KdPrint() to print it , but the result is Garbled. any ideal?

Here is my pseudo code:

double a = 1.0;

status = KeSaveFloatingPointState(&saveData);
if (NT_SUCCESS(status))
{
vspfunc(“%f”,a);
KdPrint((“%s \n”,a));

You aren’t thinking about your problem. “a” is a double. You are
passing it to KdPrint and trying to print it as a string.

Your vspfunc is putting the result in “buffer”. That’s what you want
to print. Is that a global? If so, then you should do
KdPrint(( “%s\n”, buffer ));

A better solution would be to eliminate the global, and pass a local
buffer to vspfunc. Of course, if you’re going to do that, why not just
call vsprintf directly from here and eliminate vspfunc?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks for all reply and suggestion ,

vspfunc is putting the result in global “buffer” , my vspfunc is used in
another placer
so this is why I’m not just call vsprintf ,Now I modified my code as
bellow, but it has
the same problem , is it not available to print the float number in Windows
Kernel ?

status = KeSaveFloatingPointState(&saveData);
if (NT_SUCCESS(status))
{
a = 1.0;
vspfunc(“%f”,a);
KdPrint((“vspfunc %s \n”,buffer));
KeRestoreFloatingPointState(&saveData);
}

M. M

2012/12/28 Tim Roberts

> You aren’t thinking about your problem. “a” is a double. You are
> passing it to KdPrint and trying to print it as a string.
>
> Your vspfunc is putting the result in “buffer”. That’s what you want
> to print. Is that a global? If so, then you should do
> KdPrint(( “%s\n”, buffer ));
>
> A better solution would be to eliminate the global, and pass a local
> buffer to vspfunc. Of course, if you’re going to do that, why not just
> call vsprintf directly from here and eliminate vspfunc?
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

A simple rule: never, ever use a non-const static or global variable in a
driver. (And before I get flamed, those of you who use them actually know
how to use them correctly. Most beginners have no experience to do this
right; hence the simple rule: don’t do it)

It is worth tracing the code used for %f in the vsprintf library, or
reading the source code. There is no code in that library to format a
float; it does a kernel call. I do not know what the kernel version of
vsprintf does, but the last I recall was that floating point formatting
was not supported in the kernel.
joe

xxxxx@gmail.com wrote:
> Hello everyone,
>
> I’m used KeSaveFloatingPointState and KeRestoreFloatingPointState to
> handle the floating arithmetic ,and I want to check the result , so I
> used vsprintf() to change it to string and used KdPrint() to print it ,
> but the result is Garbled. any ideal?
>
> Here is my pseudo code:
>
> double a = 1.0;
> …
> status = KeSaveFloatingPointState(&saveData);
> if (NT_SUCCESS(status))
> {
> vspfunc(“%f”,a);
> KdPrint((“%s \n”,a));

You aren’t thinking about your problem. “a” is a double. You are
passing it to KdPrint and trying to print it as a string.

Your vspfunc is putting the result in “buffer”. That’s what you want
to print. Is that a global? If so, then you should do
KdPrint(( “%s\n”, buffer ));

A better solution would be to eliminate the global, and pass a local
buffer to vspfunc. Of course, if you’re going to do that, why not just
call vsprintf directly from here and eliminate vspfunc?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

This is the kernel. You must never call something like vsprintf, which
can do a buffer overrun. The function you are calling must get the
address of the buffer, AND its length, and use something like vnsprintf.
There is no way it can know where ‘buffer’ is unless it is global, and
this is a paradigm that is deadly in a driver.

It ignores problems such as multithreading, multicore, and other
concurrency problems. It also ignores multiple device instances. Don’t
do it.

When in doubt, trace. You are treating vsprintf (normally a user-level
call) as a “black box”, and have ignored the fact that when you have a
black box that isn’t working, the right tool is a screwdriver. Open it up
and look inside.
joe

Thanks for all reply and suggestion ,

vspfunc is putting the result in global “buffer” , my vspfunc is used in
another placer
so this is why I’m not just call vsprintf ,Now I modified my code as
bellow, but it has
the same problem , is it not available to print the float number in
Windows
Kernel ?

status = KeSaveFloatingPointState(&saveData);
if (NT_SUCCESS(status))
{
a = 1.0;
vspfunc(“%f”,a);
KdPrint((“vspfunc %s \n”,buffer));
KeRestoreFloatingPointState(&saveData);
}

M. M

2012/12/28 Tim Roberts
>
>> You aren’t thinking about your problem. “a” is a double. You are
>> passing it to KdPrint and trying to print it as a string.
>>
>> Your vspfunc is putting the result in “buffer”. That’s what you want
>> to print. Is that a global? If so, then you should do
>> KdPrint(( “%s\n”, buffer ));
>>
>> A better solution would be to eliminate the global, and pass a local
>> buffer to vspfunc. Of course, if you’re going to do that, why not just
>> call vsprintf directly from here and eliminate vspfunc?
>>
>> –
>> Tim Roberts, xxxxx@probo.com
>> Providenza & Boekelheide, Inc.
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

maomao2722 wrote:

vspfunc is putting the result in global “buffer” , my vspfunc is used
in another placer
so this is why I’m not just call vsprintf ,Now I modified my code as
bellow, but it has
the same problem , is it not available to print the float number in
Windows Kernel ?

Correct. That is the fundamental problem. The kernel version of printf
simply does not support the floating point specifiers (%e %f %g).

And those are not trivial to implement…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

In 1967, I modified some code that had been written to convert floating
point numbers to a string. The code had been written by a floating-point
expert. On the whole, it was unintelligible, because wired into it was
every bizarre detail of the /360 floating point, including idiosyncrasies
related to its hexadecimal normalization and roundoff/truncation behavior.
The author claimed correctness to 1LSB on any conversion. The code was
several thousand lines of /360 assembly code. In 1969, I wrote a floating
point conversion library for the PDP-10 arcitecture. It was many hundreds
of lines of C-level code (although the language was not C). When I looked
at the Microsoft CRT sources, there is a kernel call to do the conversion.
So I can believe easily that no effort was put into making the kernel CRT
support these.

Using a global buffer ranks right up there in The List Of Really Bad
Ideas. It is a horrible thing to do in an app, and an insanely dangerous
thing to do in the kernel. Note to the OP: unless you are an experienced
driver writer who understands ALL of the consequences of a global
variable, DON’T DO IT!!! Something about angels treading comes to mind
here…

Get out of te habit of using this idiom. It is dangerous. There is truly
no valid excuse in this case for using such a poor programming technique.

And, of course, there is the question about why you are doing floating
point arithmetic in the kernel at all. Like most rules, there are rare
and exotic reasons for doing so, but you must have one of these situations
before you consider it. Note also that there are convenient tricks for
converting the floating point to a pair of integers which can be printed
out as %d.%0nd where n is the number of decimal places you need.

double d;
…compute value in d
int before = (int) d;
int after = abs( (int)(d * 1000) % 1000);
DebugPrint("%d.%03d, before, after);

This will be “close enough” because it does weird things near the limits,
but for reasonable ranges of data it is good enough. Note that it does
not do rounding; that’s left as an Exercise For The Reader. However,
proper rounding is one of those tricky things in floating point; every
piece of code I’ve seen uses weird constants that are conscious of how the
FPU works. In some cases, I’ve seen them in octal or hex because the
author discovered that the assembler/compiler, in processing the costant
written in floating point, would translate it according to its opinion of
what the translation ought to be. In one infamous case, the IBM FORTRAN-G
compiler converted source constants differently than the FORTRAN-H
compiler, and for efficiency, their runtimes used a different algorithm
that was not as precise but which ran faster (at least, both runtimes used
the same algorithm). For debugging purposes, such precision is usually
unnecessary, which is why I didn’t bother with it.

So, unless you are doing some “filter” in an audio or video cascade, you
should avoid floating point as much as possible. It is truly very rare to
need it in ordinary drivers.

Don’t think of drivers as some kind of app that happens to run in kernel
space. They are their own world, and you cannot lightly transfer app
programming habits into the kernel. And some, like the use of a global
buffer, should be abandoned entirely. In the app world, multithreading
will kill you; in the kernel, multithreading is so fundamental that you
have to assume it is always there. Global variables which are used for
gratuitous communication with subroutines are a very bad habit to have in
a multithreaded universe. A good general rule for utility conversion
routines is that they use no values except their parameters and locals.
There are exceptions, of course, but your situation is absolutely /not/
one of these exceptions!
joe

maomao2722 wrote:
>
> vspfunc is putting the result in global “buffer” , my vspfunc is used
> in another placer
> so this is why I’m not just call vsprintf ,Now I modified my code as
> bellow, but it has
> the same problem , is it not available to print the float number in
> Windows Kernel ?

Correct. That is the fundamental problem. The kernel version of printf
simply does not support the floating point specifiers (%e %f %g).

And those are not trivial to implement…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

xxxxx@flounder.com wrote:

… In 1969, I wrote a floating
point conversion library for the PDP-10 arcitecture. It was many hundreds
of lines of C-level code (although the language was not C). When I looked
at the Microsoft CRT sources, there is a kernel call to do the conversion.
So I can believe easily that no effort was put into making the kernel CRT
support these.

I wrote the float-to-ASCII and ASCII-to-float routines in the library
for the venerable MASM32 distribution. The float-to-ASCII side is 330
lines (including comments). There are some interesting tradeoffs to
make in a conversion like that, because people have their own
preconceived notions of how things should be displayed. For example, a
naïve implementation would convert the number 1/2 to “5.0000000E-001”,
which most people do not expect.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.