I'm trying to get some of the Fpu items working from C++. My buffer keeps returning "ERROR" or "0.0000000" and I'm not sure what it is that I'm doing wrong.
#define SRC1_REAL 2
#define SRC1_DMEM 4
#define SRC1_DIMM 8
#define SRC1_CONST 16
#define DEST_MEM 0
#define DEST_IMEM 64
#define DEST_FPU 128
#define SRC2_FPU 256
#define SRC2_REAL 512
#define SRC2_DMEM 1024
#define SRC2_DIMM 2048
#define SRC2_CONST 4096
#define STR_REG 0
#define STR_SCI 32768
#pragma comment(lib, "fpu.lib")
extern "C" DWORD __stdcall FpuFLtoA(DWORD lpSource, DWORD dwDecimalsNeeded, DWORD szBuffer, DWORD flags);
int main(int argc, char** args)
{
double d = 1234.123456;
DWORD perc = 10;
char szBuffer[128];
FpuFLtoA((DWORD)&d, perc, (DWORD)(char*)szBuffer, SRC1_REAL | SRC2_DIMM | STR_REG);
prinf("%s\r\n", szBuffer);
return 0;
}
Any chance that you trying to do this with M$ Visual C?
LOL. That's right. Does that make a difference?
I was looking at Raymond's doc for the function.
It mentions that the real number to string should
be an 80-bit number. But a double is a 64-bit
number. So I thought a "long double" would do the
trick. It didn't. We'll let a MS VC expert jump
in, but in the mean time try this.
#include <windows.h>
#include <stdio.h>
#define SRC1_REAL 2
#define SRC2_DIMM 2048
#define STR_REG 0
#pragma comment(lib, "fpu.lib")
extern "C" DWORD __stdcall FpuFLtoA(DWORD *lpSource, DWORD dwDecimalsNeeded, char *szBuffer, DWORD flags);
int main(int argc, char** args)
{
long double d = 1234.123456;
DWORD perc = 10;
char szBuffer[128], flt[10];
__asm {
fld d
fstp TBYTE PTR [flt]
}
FpuFLtoA((DWORD *)&flt, perc, szBuffer, SRC1_REAL | SRC2_DIMM | STR_REG);
printf("%s\r\n", szBuffer);
return 0;
}
That works! I tried the "long double" but that still gave off errors. Thanks for your help!!!
'long double' in MSVC is 64-bit. The 80-bit extended precision floating-point data type is not supported in MSVC.
But it is in MASM! You can do all your calculations in MASM with REAL10 and then save the final result as a REAL8 (double) if you want to use it in MSVC. Use a separate MASM file and link it with the C program.
You can use fpu.lib from C if you really want to. You use void pointers for the REAL10 variables. I was just fiddling around with it once and got it to work.
Here is the fpu.h file
// Raymond Filiatreault's FpuLib
// http://www.ray.masmcode.com
//
#pragma comment(lib, "c:\\masm32\\lib\\fpu.lib")
//
int __stdcall FpuAtoFL(char* lpszSrc, void* lpDest, unsigned int UID);
int __stdcall FpuFLtoA(void* lpSrc1, int* lpSrc2, char* lpszDest, unsigned int uID);
//
int __stdcall FpuAdd(void* lpSrc1, void* lpSrc2, void* lpDest, unsigned int uID);
int __stdcall FpuSub(void* lpSrc1, void* lpSrc2, void* lpDest, unsigned int uID);
int __stdcall FpuMul(void* lpSrc1, void* lpSrc2, void* lpDest, unsigned int uID);
int __stdcall FpuDiv(void* lpSrc1, void* lpSrc2, void* lpDest, unsigned int uID);
int __stdcall FpuSqrt(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuXexpY(void* lpSrc1, void* lpSrc2, void* lpDest, unsigned int uID);
int __stdcall FpuAbs(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuTrunc(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuRound(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuChs(void* lpSrc, void* lpDest, unsigned int uID);
//
int __stdcall FpuLnx(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuLogx(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuEexpX(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuTexpX(void* lpSrc, void* lpDest, unsigned int uID);
//
int __stdcall FpuSin(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuCos(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuTan(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArcsin(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArccos(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArctan(void* lpSrc, void* lpDest, unsigned int uID);
//
int __stdcall FpuSinh(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuCosh(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuTanh(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArcsinh(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArccosh(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuArctanh(void* lpSrc, void* lpDest, unsigned int uID);
//
int __stdcall FpuSize(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuComp(void* lpSrc, void* lpDest, unsigned int uID);
int __stdcall FpuExam(void* lpSrc, unsigned int uID);
int __stdcall FpuState(void* lpSrc, unsigned int uID);
#define SRC1_FPU 1
#define SRC1_REAL 2
#define SRC1_DMEM 4
#define SRC1_DIMM 8
#define SRC1_CONST 16
#define ANG_DEG 0
#define ANG_RAD 32
#define DEST_MEM 0
#define DEST_IMEM 64
#define DEST_FPU 128
#define SRC2_FPU 256
#define SRC2_REAL 512
#define SRC2_DMEM 1024
#define SRC2_DIMM 2048
#define SRC2_CONST 4096
#define STR_REG 0
#define STR_SCI 32768
#define FPU_PI 1
#define FPU_NAPIER 2
#define XAM_VALID 1
#define XAM_ZERO 2
#define XAM_NEG 4
#define XAM_SMALL 8
#define XAM_INFINIT 16
#define CMP_EQU 1
#define CMP_GREATER 2
#define CMP_LOWER 4
and here is the example code real10.c for MSVC 6.0
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "fpu.h"
int print_real10(void* pExt, int precision);
void waitkey(void);
int main(void)
{
int x;
void* pExt;
unsigned char* pCh;
// allocate room for the REAL10 variable
pExt = malloc(10);
// save Pi to the REAL10 variable
_asm
{
finit
fldpi
mov eax, pExt
fstp TBYTE PTR [eax]
}
pCh = pExt;
// print out the bytes
printf("Pi (REAL10) = ");
for( x = 9 ; x >= 0 ; x-- )
{
printf("%02hhX ", *(pCh + x));
}
printf("\n");
// print using FpuFLtoA
printf("Pi (REAL10) = ");
print_real10(pExt, 16);
printf("\n");
free(pExt);
waitkey();
return 0;
}
int print_real10(void* pReal10, int precision)
{
int rv;
char szBuff[64];
RtlZeroMemory(szBuff, sizeof(szBuff));
rv = FpuFLtoA(pReal10, (int*) precision, szBuff, SRC1_REAL | SRC2_DIMM | STR_REG);
printf("%s", szBuff);
return rv;
}
void waitkey(void)
{
int ch;
printf( "\nPress any key to continue...");
ch = _getch();
if(ch == 0 || ch == 0xE0)
{
_getch();
}
printf("\n");
}