2011-01-06 7 views
2

Ich versuche, eine 32-Bit-Gleitkommazahl in eine erweiterte Gleitkommazahl mit 80 Bit zu konvertieren. Ich benutze MSVC x86. Ich habe versucht, den folgenden Inline-ASM-Code:Konvertieren von 32-Bit-Gleitkommazahl nach IEEE 80-Bit

void Convert32To80(float *value, void *outValue) 
{ 
    __asm 
    { 
     fld float ptr [value]; 
     fstp tbyte ptr [outValue]; 
    } 
} 

Hier void *outValue ist ein Puffer, der groß genug ist, 10 Bytes zu halten. Das sieht gut aus, aber es stürzt ab, wenn es läuft.

Jede Hilfe wird geschätzt!

+0

"Absturz beim Ausführen." Welche spezifischen Fehler bekommen Sie? – James

+0

Ich erhalte keinen spezifischen Fehler. Es ist eine C++/CLI-DLL, die aus verwaltetem Code geladen wird (es ist etwas mit dem ASM, andere Inline-ASM-Stubs funktionieren gut). Ich bekomme dies: "Die Laufzeit hat einen schwerwiegenden Fehler festgestellt. Die Adresse des Fehlers war bei 0x64f9fca1, auf Thread 0x1904. Der Fehlercode ist 0xc0000005. Dieser Fehler kann ein Fehler in der CLR oder in der unsicheren oder nicht Nachprüfbare Teile des Benutzercodes: Häufige Ursachen für diesen Fehler sind Fehler bei der Benutzermarshalation für COM-Interop oder PInvoke, die den Stack beschädigen können. " – Janiels

+1

Sie müssen mit Ihrem Debugger überprüfen, welche Anweisung den Absturz verursacht. Vielleicht ist Ihr outValue schlecht (NULL oder so ähnlich)? – Suma

Antwort

3

OK, das sollte es tun:

void Convert32To80(float *value, void *outValue) 
{ 
    __asm 
    { 
     mov eax,dword ptr [value] 
     fld dword ptr [eax] 
     mov ecx,dword ptr [outValue] 
     fstp tbyte ptr [ecx] 
    } 
} 

Alles, was ich war etwas C-Code tat schrieb das gleiche zu tun, aber für einen Schwimmer Doppelumwandlung, bei der dissasembly geschaut und dann nach Bedarf modifiziert.

Beachten Sie, dass ich kein Experte mit MSVC bin und ich bin nicht 100% sicher, dass ich die EAX und ECX-Register so verwenden kann, ohne sie zu speichern/wiederherzustellen. Andere wissen vielleicht mehr und bieten Korrekturen an.

+0

Vielen Dank! Das hat funktioniert. Dachte nicht, dass "Wert" innerhalb der Inline-ASM der Zeiger auf den Stack wäre! Nochmals vielen Dank. Über die EAX- und ECX-Register sagt der Intel ABI, dass sie verwendet werden können, ohne sie zu speichern, also sollte das kein Problem sein. – Janiels

+0

Vorsicht! Nicht alle folgen dem Intel ABI. Am besten sollten Sie sich beim Compileranbieter erkundigen, da sie die einzige sind, die das sicher weiß. –

+0

@Brian, @Jakob Ich dachte dasselbe, war mir aber nicht sicher, wie ich mich ausdrücken sollte. Ich schaute auf eine ähnliche Routine, aber mit reinem C codiert und nur ein Float zu einem Doppel zuweisen. Prolog und Epilog waren im Wesentlichen identisch.Aber ich stimme zu, ich würde gerne die Konventionen zum Speichern von Registern prüfen, aber ich weiß wirklich wenig von MSVC, das eher ein Borland-Typ ist. –

1

Aktualisiert Hinweis für die Nachwelt: Offenbar MSVC 2010 hat keinen Typen für 80bit Punkttypen schwimmen, so die offensichtliche Lösung in C oder C++ Code entlang der Linien von

float inValue = 666.666f; 
long double outValue = (long double)inValue; 

nicht funktioniert, und Sie sind gezwungen, Assemblersprache direkt zu benutzen.

+1

Würde in der Tat, außer in MSVC 2010 Long Double ist ein Synonym für Double, das ist 64-Bit. – Janiels