Code-Beispiel
FPU check
| Lizenz: | Erster Autor: | Letzte Bearbeitung: | 
| LGPL |  Volta |  26.11.2015 | 
Nur 32 Bit
Wozu braucht man das?
Berechtigte Frage, eigentlich nur wenn man mit FPU-ASM-Befehlen experimentiert.
Was macht der FPU_check?
Er sichert in einem 512 Byte - Array relevante Daten der FPU ohne sie zu ändern.
Ausgewertet erhält man einen Überblick wie der konkrete Zustand der FPU ist.
FPU_check.bas :
' "FPU_check.bas" by Volta 16.01.2008
' Idee aus:
'- FPU-Helferlein
'- "Helle" Klaus Helbing, 12.08.2007, PB4.02
' http://www.purebasic.fr/german/viewtopic.php?t=13878
Union ext
  As ULongInt fli(0 To 2-1)
  As Double fd
End Union
Type fx_save Field = 2
  As UShort FPUCW
  As UShort FPUSW
  As UByte Tag
  As UByte resTag
  As UShort Opcode
  As ULongInt res0h
  As ULongInt res1l
  As ULongInt res1h
  As ext FST(0 To 8-1)
  As ULongInt res(0 To 44-1)
End Type
Dim Shared As fx_save xsave
Sub FPU_check ()
  Asm
    lea esi, [xsave]
    fxsave [esi]            '512 Byte in -> xsave sichern
    fwait
    fld  tbyte Ptr[esi+32]  'ST(0)|MM0 -> xsave.FST(0).fd
    fstp qword Ptr[esi+32]
    fld  tbyte Ptr[esi+48]  'ST(1)|MM1 -> xsave.FST(1).fd
    fstp qword Ptr[esi+48]
    fld  tbyte Ptr[esi+64]  'usw
    fstp qword Ptr[esi+64]
    fld  tbyte Ptr[esi+80]
    fstp qword Ptr[esi+80]
    fld  tbyte Ptr[esi+96]
    fstp qword Ptr[esi+96]
    fld  tbyte Ptr[esi+112]
    fstp qword Ptr[esi+112]
    fld  tbyte Ptr[esi+128]
    fstp qword Ptr[esi+128]
    fld  tbyte Ptr[esi+144] 'ST(7)|MM7 -> xsave.FST(7).fd
    fstp qword Ptr[esi+144]
    fwait
  End Asm
  Dim As Integer i,x
  Dim As UByte b = 128
  Print "------FPU_check------"
  Print "FPU - Register"
  Print "Controlword = ";Hex(xsave.FPUCW,4)
  Print "Statusword  = ";Hex(xsave.FPUSW,4)
  x = (xsave.FPUSW And &h3800) Shr 11
  For i = 0 To 7
    If i = x Then
      Print "TOS ";         'Top of stack
    Else
      Print "    ";
    End if
    Print "ST(" & i & ") ";
    If (xsave.Tag And b) Then
      Print "Belegt =";     'locked
    Else
      Print "  Frei =";     'free
    End If
    Print xsave.FST(i).fd
    b\=2
  Next
  Print "----------------Ende-"
End Sub
Ausgabe:
------FPU_check------
FPU - Register
Controlword = 037F
Statusword  = 0220
TOS ST(0)   Frei = 0
    ST(1)   Frei = 0
    ST(2)   Frei = 0
    ST(3)   Frei = 0
    ST(4)   Frei = 0
    ST(5)   Frei = 1
    ST(6)   Frei = 6919435305.535846
    ST(7)   Frei = 6919435305.535846
----------------Ende-
Controlword, Statusword, TOS (Top of stack) und der Inhalt aller Register wird angezeigt. 
Zusätzlich wird angezeigt ob die Register "Belegt" oder "Frei" sind, wichtig, da ein belegtes Register nicht überschrieben werden kann.
Die nachfolgende Funktion x_Pow(y) (=x^y) war der Anlass den FPU_check zu schreiben.
Sah elegant aus und arbeitete recht schnell aber nach mehrfachem Aufruf gab es nur noch falsche Ergebnisse.
Fehler_check.bas :
'Fehlertest mit FPU_check by Volta 16.01.2008
#Include "FPU_check.bas"
Function x_Pow(a As Double,b As Double) As Double
  Asm
    fld qword Ptr [b]        'st(0) = b
    fld qword Ptr [a]        'st(0) = a ;st(1) = b
    fyl2x                    'st(0) = ln(a)*b
    fst   st(1)              'in st(1) kopieren
    frndint             'st(0) runden = Integer-Anteil
    fsub  st(1),st(0)   'st(1) Vorkommaanteil auf 0 setzen
    fld1                '1 laden
    fscale              'temp:= 2 hoch Integer-Anteil
    fld   st(2)         'Nachkommaanteil laden
    f2xm1               '2 hoch Nachkommaanteil -1
    fld1                '1 laden
    faddp st(1),st(0)   '+1
    fmulp st(1),st(0)   '*temp
    'fstp st(1)
    'fstp st(1)
    fstp qword Ptr [Function]
  End Asm
End Function
Dim j As Integer
Dim As Double x=8.2123, n=-3.1,y
y=x^n
FPU_check
?y
Sleep
?
For j = 1 To 10
  y=x_Pow (x,n)
  FPU_check
  ?y
  Sleep
Next j
Print "verdisch.."
Sleep
Es stellte sich heraus, dass nicht alle Werte vom Stack der FPU entfernt wurden und einige Register gesperrt blieben.
Macht der FBC auch solchen Unsinn?
'Test FBC mit FPU_check by Volta 16.01.2008
#Include "FPU_check.bas"
FPU_check
Sleep
Cls
Dim As Double x=3.2, y=4.76
x=x+y
FPU_check
Print x
Sleep
x=Sin(y)
FPU_check
Print x
Sleep
x=Sqr(y)
FPU_check
Print x
Sleep
x=Exp(y)
FPU_check
Print x
Sleep
x=x^y
FPU_check
Print x
Print "verdisch.."
Sleep
EndNein, sauber programmiert!
| Zusätzliche Informationen und Funktionen | |||||||
|---|---|---|---|---|---|---|---|
| 
 
 | |||||||

 Wer ist online?
 Wer ist online? Buchempfehlung
 Buchempfehlung
 FreeBASIC-Chat
 FreeBASIC-Chat
 FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!
			FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us! Bearbeiten
 Bearbeiten Versionen
 Versionen