AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Trunc / Frac -> Wie funktionieren die intern?
Thema durchsuchen
Ansicht
Themen-Optionen

Trunc / Frac -> Wie funktionieren die intern?

Ein Thema von SebE · begonnen am 27. Okt 2005 · letzter Beitrag vom 28. Okt 2005
Antwort Antwort
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#1

Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 11:12
Hat jemand den Source der beiden Funktionen?
Hab leider keine Ahnung, wie die beiden intern funktionieren könnten.

Ich dachte erst bei TRUNC:
Result := Zahl div 1 //DIV funktioniert aber NUR bei Ganzzahl und FRAC:
Result := Zahl - Trunc(Zahl); Kann mir das jemand sagen?

Danke
Sebastian
  Mit Zitat antworten Zitat
SMO

Registriert seit: 20. Jul 2005
178 Beiträge
 
Delphi XE6 Professional
 
#2

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 12:48
Trunc, Frac und auch Round sind allesamt in Assembler programmiert. Sie benutzen also den speziellen Befehlssatz des Prozessors für Gleitkommazahlen und sind nicht durch Delphianweisungen realisiert.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 16:39
Genau, die übergeben den Wert an die FPU, sagen dieser den zu verwendenten Rundungsmodus und lesen den Wert wieder aus.

Allerdings ist Trunc tatsächlich ein klein wenig umständlicher geschrieben (was aber wohl nicht ganz stören sollte)


Wenn du es aber mal ganz genau wissen willst, dann schau entweder in die Quelltexte rein, oder mach dir'n Demoprogramm uns schau dir dort an was als ASM-Code wirklich ausgeführt wird.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#4

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 16:51
Einfach mal als Beispiel an Trunc:
Delphi-Quellcode:
{ *********************************************************************** }
{                                                                         }
{ Delphi / Kylix Cross-Platform Runtime Library                           }
{ System Unit                                                             }
{                                                                         }
{ Copyright (c) 1988-2004 Borland Software Corporation                    }
{                                                                         }
{ Copyright and license exceptions noted in source                        }
{                                                                         }
{ *********************************************************************** }

procedure _TRUNC;
asm
       { ->    FST(0)   Extended argument       }
       { <-    EDX:EAX  Result                  }

        SUB ESP,12
        FNSTCW [ESP].Word // save
        FNSTCW [ESP+2].Word // scratch
        FWAIT
        OR [ESP+2].Word, $0F00 // trunc toward zero, full precision
        FLDCW [ESP+2].Word
        FISTP qword ptr [ESP+4]
        FWAIT
        FLDCW [ESP].Word
        POP ECX
        POP EAX
        POP EDX
end;
......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#5

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 17:18
Danke für die Antworten.
Den Code hab ich auch schon mal gesehen.
Da ich aber kein Assembler kann, weis ich absolut nicht, was der macht, vor allem das FWAIT.
Und warum POP't man die Register ECX, EAX, EDX am Ende, wenn man doch gar nicht's gePUSH't hat?

Auch warum man am Anfang 12 Bytes vorrutscht, versteh ich nicht.

Und bei den Funktionen FNSTCW und FLDCW hört's ganz auf.

Wäre schön, wenn sich jemand finden würde, der den Code erklären kann.
Sebastian
  Mit Zitat antworten Zitat
SMO

Registriert seit: 20. Jul 2005
178 Beiträge
 
Delphi XE6 Professional
 
#6

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 27. Okt 2005, 23:14
Zitat von SebE:
Da ich aber kein Assembler kann, weis ich absolut nicht, was der macht, vor allem das FWAIT.
FWAIT (auch bekannt als WAIT) sorgt dafür, dass die CPU wartet, bis die FPU ihre aktuelle Operation beendet hat. Vor dem Pentium oder dem 80486 war die FPU ein externer, optionaler Koprozessor und musste daher mit dem Hauptprozessor synchronisiert werden. Wenn nämlich mehrere Prozessoren auf denselben Speicher zugreifen, kann es zu sogenannten Wettlaufsituation kommen. Das erste FWAIT im Trunc-Quelltext ist so ein Fall. Es trennt einen FPU- und einen CPU-Befehl, die dieselbe Speicherzelle manipulieren. Der CPU-Befehl soll natürlich erst dann ausgeführt werden, wenn der FPU-Befehl fertig ist.

Heutzutage ist die FPU in der CPU integriert. Wenn ich micht nicht irre braucht man deshalb solche FWAITs nicht mehr wirklich. Aber Borland will den Code wohl kompatibel zu älteren Prozessoren halten.
Außerdem sorgt FWAIT noch dafür, dass anliegende FPU Exceptions sofort behandelt werden und das ist auch auf modernen Prozessoren noch relevant. Denn wenn eine FPU Exception auftritt, wie z.B. eine Division durch Null, dann passiert erst mal gar nichts. Das Programm könnte munter weiterlaufen, bis zum nächsten FPU Befehl, der auf anliegende Exceptions prüft.

Zitat:
Und warum POP't man die Register ECX, EAX, EDX am Ende, wenn man doch gar nicht's gePUSH't hat?

Auch warum man am Anfang 12 Bytes vorrutscht, versteh ich nicht.
Das hängt beides zusammen.
Der erste Befehl reserviert 12 Bytes auf dem Stack, quasi lokale Variablen. Nämlich 2 Bytes, um das aktuelle FPU Control Word zu sichern (save) und später zu restaurieren, 2 Bytes zum Basteln des neuen Control Words (scratch) und schließlich 8 Bytes für das Ergebnis.

Zitat:
Und bei den Funktionen FNSTCW und FLDCW hört's ganz auf.
FNSTCW = STore Control Word. Alle FPU Befehlsnamen fangen mit "F" an und das "N" hier bedeutet, dass anliegende FPU Exceptions nicht behandelt (also ignoriert) werden.
FLDCW = LoaD Control Word.
Das Control Word ist ein 16-Bit-Wort, das gewisse Einstellungen der FPU enthält, unter anderem wie gerundert wird und mit welcher Präzision gearbeitet wird.


Zitat:
Wäre schön, wenn sich jemand finden würde, der den Code erklären kann.
Ich hoffe, das habe ich gerade einigermaßen gut getan.

Falls nicht, hier alles nochmal zusammenhängend:

Delphi-Quellcode:
procedure _TRUNC;
asm
   // Eingabe: Extended-Wert, der gerundet werden soll, in FST(0)
   // Ausgabe: Int64-Wert in EDX:EAX

   // Platz für lokale/temporäre Variablen auf dem Stack reservieren
   SUB ESP,12
   // FPU Control Word auf reservierten Stackplatz sichern
   FNSTCW [ESP].Word // save
   // und noch eine zweite Kopie sichern
   FNSTCW [ESP+2].Word // scratch
   // warten, bis FPU mit obigem Befehl fertig ist
   FWAIT
   // bestimmte Bits der 2. Stack-Kopie des Control Words auf 1 setzen, sodass FPU auf 0
   // abrundet (also Nachkommastellen abschneidet) und mit voller Präzision rechnet
   OR [ESP+2].Word, $0F00 // trunc toward zero, full precision
   // modifizierte Stack-Kopie des Control Words in FPU laden und somit aktivieren
   FLDCW [ESP+2].Word
   // jetzt kommt die eigentliche Arbeit ;)
   // Gleitkommawert, der sich gerade in ST(0) befindet (also unser Parameter) als
   // Integer auf den Stack nach [ESP+4] speichern und dabei gemäß des aktuellen
   // Control Words runden (truncate!)
   // Außerdem wird der FPU-Registerstack "gePOPpt", aber das tut hier nichts zur Sache
   FISTP qword ptr [ESP+4]
   // wenn eine FPU Exception aufgetreten ist, dann jetzt sofort behandeln
   // Es könnte ja versucht worden sein, einen Wert zu runden, der so groß (oder so klein)
   // ist, dass er nicht mehr als Int64 dargestellt werden kann. Wenn das der Fall war,
   // wollen wir an dieser Stelle informiert werden und nicht erst unabsehbar später.
   FWAIT
   // ursprüngliches FPU Control Word wieder restaurieren (zurück in die FPU laden)
   FLDCW [ESP].Word
   // ursprüngliches und modifiziertes Control Word vom Stack entfernen
   // die Werte sind jetzt unwichtig, man könnte genausogut ADD ESP,4 schreiben, aber
   // der Befehl POP ECX ist kleiner und ECX darf gefahrlos verändert werden
   POP ECX
   // gerundetes Ergebnis vom Stack entfernen und in die Register EDX:EAX laden
   POP EAX
   POP EDX
end;
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#7

Re: Trunc / Frac -> Wie funktionieren die intern?

  Alt 28. Okt 2005, 11:09
Ich danke dir.

Schön, dass du dir die Zeit genommen hast, mir das ganze so umfangreich zu erklären

Sebastian
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz