Float Vergleich
-
Moin,
Dieser Code funktioniert einfach nicht. Ich will zwei globale float-Variablen a und b so vergleichen : "a < b"?. Ich habe eine int-Variable, in der eine 1 steht, wenn a < b ist, sonst steht 0 drinnen. Am Ende stet in der Variablen aber leider eine 0 drinnen:
float a = 10, b = 20; int erg;
__asm { MOV DWORD PTR[erg],0 FLD DWORD PTR[a] FLD DWORD PTR[b] FCOMPP SUB ESP, 4h FSTSW WORD PTR[ESP] POPFD JNB after MOV DWORD PTR[erg], 1 after: }
Kann mir da mal bitte jemand weiterhelfen?
-
Du weist die Condition Codes nicht richtig zu: diese befinden sich im high Byte des SW und müssen in das unterste Byte des Flagregisters:
pop eax sahf
Außerdem lädst du die Vergleichsoperanden verkehrt herum (was an sich kein Problem darstellt
).
Aus Performance-Gründe, sollte man heute den Befehl FCOMIP verwenden, der direkt die Flags setzt:MOV DWORD PTR[erg],0 FLD DWORD PTR [b] FLD DWORD PTR [a] FCOMIP st(0),st(1) fstp st setb BYTE PTR[erg]
-
Aus welchem Grund genau geht denn "POPFD" nicht?
-
Jeff123 schrieb:
Aus welchem Grund genau geht denn "POPFD" nicht?
Vergleich das Flags-Register mit dem FPU status word: AMD64 Architecture Programmer's Manual Volume 1: Application Programming
Für SAHF und POPFD: AMD64 Architecture Programmer's Manual Volume 3: General Purpose and System Instructions
-
Es ist aber kein AMD sondern ein Intel 32-Bit System
-
Was ich nicht verstehe ist: Was ist der Unterschied zwischen meinem POPFD, das das "Status word" der FPU direkt ins das EFlags-Register kopiert und deinem Vorschlag, wo du ebenfalls ein POP-Befehl verwendest, das den Statusword erst in EAX speichert und dann im Statusregister der CPU??. Wo liegt der Unterschied?
-
Jeff123 schrieb:
Was ich nicht verstehe ist: Was ist der Unterschied zwischen meinem POPFD, das das "Status word" der FPU direkt ins das EFlags-Register kopiert und deinem Vorschlag, wo du ebenfalls ein POP-Befehl verwendest, das den Statusword erst in EAX speichert und dann im Statusregister der CPU??. Wo liegt der Unterschied?
Das Bit, das Dich bei FCOMPP interessiert, ist das Bit8 des FPU-Statusworts, also das neunte Bit von rechts. Wenn Du das Statuswort auf dem Stack speicherst und dann mit POPFD in die eFlags kopierst, dann landet das Bit8 auch dort auf Bit8. In den eFlags sitzt aber dort das I-Flag und nicht das C-Flag. Wenn Du das I-Flag veränderst, bekommst Du einen grandiosen Absturz.
In den eFlags sitzt das C-Flag (Carry) bei Bit0. Um das Bit8 des Statuswords in das Bit0 der eFlags zu bekommen, nimmt man die Folge "FSTW AX - SAHF" (Statuswort nach AX, AH in die Flags) und lässt den Stack schön in Ruhe, weil:
-
Du speicherst das 16-Bit-Statusword auf dem Stack und popst 32 Bit in die eFlags. Die restlichen 16 Bit auf dem Stack haben irgendeinen Wert, der dann auch im eFlags-Register landet.
-
Mit POPFD veränderst Du alle Bits des eFlags-Registers. Dort befinden sich aber nicht nur informative Flags (z.B. Carry, Zero, Aux), sondern auch Flags, die den Prozessormodus betreffen (z.B. Direction, Interrupt). Diese Flags darfst Du nicht so einfach antasten.
Intel- und AMD-Prozessoren sind weitgehend identisch. Du kannst Dich also für gängige Befehle und Vorgehensweisen bei beiden Manuals bedienen. Außerdem sind die Prozessoren abwärtskompatibel. Was im IA64-Manual für 32-Bit steht, gilt auch für IA32-Prozessoren.
viele grüße
ralph
-