Wenn Sie die FPU verwenden möchten Beachten Sie, dass es einen gestapelten Satz von Registern verwendet, die nur aus dem Speicher geladen oder im Speicher gespeichert werden können.
Ich nehme an, dass Sie über das FPU-Programmiermodell selbst dokumentieren können, indem Sie entweder die Intel manual 1 oder, wenn Sie sich nostalgisch fühlen, von reading this 387 manual from Intel dated 05/26/1987.
Die Anweisung fstp dword [eax]
speichern den Inhalt von st(0)
bei bezeichnet die Adresse von eax
. Diese Art von Adressierungsmodus ist ein indirekter Adressierungsmodus und wird durch die Verwendung von eckigen Klammern in der Intel-Assembly-Syntax konsequent markiert.
Vergleichen Sie dies mit Speichern st(0)
in eax
, die wie fstp eax
(keine Klammern) aussehen sollte.
Leider wird Letzteres nicht unterstützt, wahrscheinlich weil die FPU 64-Bit- und 80-Bit-Formate unterstützt, die zu diesem Zeitpunkt nicht in ein Register passen.
Um Daten zu pushen. aus dem Speicher in den FPU-Stack fld
verwenden, um die Register in den Speicher zu laden, verwenden Sie fstp
(oder , wenn Sie den Stack nicht öffnen möchten).
Um eine Multiplikation durchzuführen fmul
, kommt es in einigen Varianten, von denen einer mit einem Speicheroperanden arbeiten und das Ergebnis direkt in st(0)
speichern kann.
Wenn Sie sich paranoid fühlen, können Sie am Anfang des Programms finit
verwenden, dieser Befehl setzt die Steuerregister der FPU zurück, um die Register leer zu markieren.
Das Betriebssystem sollte Ihren Prozess bereits mit einem sauberen Zustand starten.
Hier ein einfaches Beispiel:
.DATA
A dd 5.0
B dq 0.008
C dd 0 ;Move into a BSS section if the assembler support it
.CODE
finit ;For paranoid only
fld DWORD [A] ;ST(0) = A
fmul QWORD [B] ;ST(0) = ST(0)*B = A*B
fstp DWORD [C] ;C = ST(0) = A*B
mov eax, DWORD [C] ;EAX = C = A*B
call writefloat
Wie heute können Sie die Vektorregister mit skalaren Befehle verwenden.
Die entsprechende Dokumentation finden Sie noch im zuvor verlinkten Intel-Handbuch.
.DATA
A dd 5.0 ;Use float
B dd 0.008 ;Use float again, avoid cvtss2sd
C dd 0 ;Move into a BSS section if the assembler support it
.CODE
movss xmm0, DWORD PTR [A] ;xmm0.f[0] = A
mulss xmm0, DWORD PTR [B] ;xmm0.f[0] = A * B
movd eax, xmm0 ;eax = xmm0.f[0] = A * B
;Beware, 1 extra cycle for bypass delay
call writefloat
Dieser Code lädt 'fin' und multipliziert ihn mit' fin'. Das ist das gleiche wie fin^2 (quadriert). Ihre 'fmul' sollte als ihren Operanden den Wert nehmen, den Sie mit' fin' * multiplizieren * wollen. Aber der Code stimmt nicht mit der Frage überein, da "fin" eine Konstante von 5.0 ist, während man davon ausgeht, dass man 3.02 x 0.008 multipliziert. –