View Single Post
  #27   Report Post  
Posted to microsoft.public.excel,microsoft.public.excel.programming
Martin Brown Martin Brown is offline
external usenet poster
 
Posts: 230
Default Excel and the Math Coprocessor for DLLs

On 31/03/2012 23:17, joeu2004 wrote:
"Lynn McGuire" wrote:
I have created a test app at
www.winsim.com/testdll.zip


When I open testdll.xls and look at CommandButton1_Click, the relevant
code that I see is a call to InitTestDLL.

When I look at InitTestDLL in testdll.c, the relevant code that I see is:

1. The chptst calculation, which is displayed using MessageBox.
2. A call to capsmn().
3. A call to checkMathCoprocessorStatus [sic].

When I look at checkMathCoprocessorStatus, the relevant code that I see is:

1. old87Control = _control87 (0, 0).
2. Commented-out code that might change the FP control word (FPCW).
3. new87result = _control87 (0, 0)
4. A call to MessageBox to display old87Control and new87Result.


"Lynn McGuire" wrote:
Just load testdll.xls into Excel (I am using Excel
2003 but any should work OK). Then press the RUN
button on the spreadsheet. The first time, all is
OK. The second time, the chptst calc in the C DLL
code exhibits the calc failure


By "OK", I presume you mean chptst is exactly zero. And by "failure", I
presume you mean that chptst is non-zero, namely about 2.851266E-10.

And that is indeed what I observe, as well, when I execute
CommandButton1_Click in testdll.xls.

But that behavior makes no sense based on my summary of the InitTestDLL
and checkMathCoprocessorStatus functions above.

(See the speculative explanation at the end below.)


Having had a look at a disassembly of the DLL code it looks like the C
bindings are resetting the numeric coprocessor on *exit* with an FPINIT
instruction which puts the arithmetic into 80bit mode nearest rounding.

The first time InitTestDLL is called, the FPCW should be set according
to VBA. We know that _PC_64 + _RC_NEAR. So chptst should be the non-zero
value ("failure").


Actually no - it looks like VBA/XL uses _PC_53 + _RC_NEAR on entry which
is why the test code gives the "right" answer first time through.

(although inside compiled floating point expressions computations on the
stack may well be done as if _PC_64 was selected)

And her compiler returns bare metal X87 status words 0x127F works
But on subsequent calls the FPRESET state 0x137F prevails since that is
what C has forced it to!

Third digit 2 vs 3 is 53bit mantissa REAL*8 vs 64bit mantissa REAL*10

The second time InitTestDLL is called, __if__ the FPCW were set to
_RC_53, chptst should be zero ("OK").


Indeed but since as its parting shot the C DLL resets the NPU to 80bit
mode this condition is not met. The failure is in the exit from the C
binding code. For once XL appears to be innocent on all counts.

--
Regards,
Martin Brown