Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Code-Beispiel

Code-Beispiele » Mathematik

FPU check

Lizenz:Erster Autor:Letzte Bearbeitung:
LGPLRedakteurVolta 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

End

Nein, sauber programmiert!


Zusätzliche Informationen und Funktionen
  • Das Code-Beispiel wurde am 17.01.2008 von RedakteurVolta angelegt.
  • Die aktuellste Version wurde am 26.11.2015 von RedakteurVolta gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen