Gleitkommazahlen P4 Gnu ASM
-
Hallo Forum,
ich versuche mich zum ersten Mal an Gleitkommazahlen. Leider mit wenig Erfolg. Laut Intel instruction set will FLD unter anderem als Parameter:
FLD m32fpAlso hab ich einiges durchprobiert:
fld $4oder
bla: .float 3
fld $blaoder:
mov $3, %eax
fld %eaxDas Einzige was funktioniert hatte war über den Stack.
push $3
fld (%esp)Was genau meint das m32fp?
Danke für jede nützliche Antwort
PS: Noch ne kleine Frage hinten dran.
Kann man in der instruction set Doku irgendwo ablesen wie viele Takte ein Befehl braucht?
-
r2p2 schrieb:
Was genau meint das m32fp?
Ich wuerde mal behaupten, das meint ein 32Bit float im Speicher.
Dann noch einige Kommentare zu deinen Versuchen:r2p2 schrieb:
Also hab ich einiges durchprobiert:
fld $4 - ist weder Float noch Speicherzugriffoder
bla: .float 3
fld $bla - ditooder:
mov $3, %eax
fld %eax - Zugriff via Register ist auch nicht moeglichDas Einzige was funktioniert hatte war über den Stack.
push $3
fld (%esp) - klar, ist zwar auch kein float, aber immerhin ein Speicherzugriffr2p2 schrieb:
PS: Noch ne kleine Frage hinten dran.
Kann man in der instruction set Doku irgendwo ablesen wie viele Takte ein Befehl braucht?Ich kenne diese Intel Doku nicht. Wenn es nicht offensichtlich ist, schau doch auch mal in anderen Referenzen nach (siehe zB. auch FAQ).
-
Ok. Ich seh ein das der was aus dem Speicher haben will.
Das mit dem Stack finde ich aber sehr unpraktisch.In einem Buch das vor mir liegt schieben die ein
A DD 3.5
aus dem Datensegment über
FLD A
in das Register.Klappt nur bei meinem gnu asm net
äußerst merkwürdig...
-
r2pr2 schrieb:
Ok. Ich seh ein das der was aus dem Speicher haben will.
Das mit dem Stack finde ich aber sehr unpraktisch....? Muss doch nicht ueber den Stack laufen.
r2pr2 schrieb:
In einem Buch das vor mir liegt schieben die ein
A DD 3.5
aus dem Datensegment über
FLD A
in das Register.Da wird halt einfach ein 32Bit float im Speicher beim Label "A" abgelegt und dann geladen. Wie das in AT&T-Syntax, spezieller beim GAS aussehen muss, kann ich dir aber leider auch nicht sagen.
-
Hallo,
so sollte es gehen:
a: .float 1.0 b: .double 1.0 flds a fldl b
Variable a ist ein float, 4 Bytes, geladen wird mit der Instruktion flds (s steht für single (= float)). Variable b ist ein double, 8 Bytes, geladen wird mit der Instruktion fldl (l steht für long...).
Wenn du so was machst:movl $a, %eax
dann wird die Adresse von a nach eax geladen.
Schreibst du dagegen so was:movl a, %eax
Dann wird das, was an der Adresse a steht (in unserem Fall ein float, 1.0, in hex 3FF00000h o.ä.), nach eax geladen.
Das ist auf den ersten Blick ungewohnt und manch einer bekommt davon "Augenkrebs" (hatte das irgendwo hier im Forum gelesen), ist aber nach einiger Zeit, wenn man sich daran gewöhnt hat, sehr logisch.
Wenn man das oben berücksichtigt, müsste es auch noch so funktionieren:movl $a, %eax flds (%eax)
Die Adresse von a nach eax, danach direkt Adresse in eax benutzen, um auf die Variable zuzugreifen...
Hoffe, es hilft weiter.
-
Kurze Anmerkung noch:
Das Einzige was funktioniert hatte war über den Stack.
push $3
fld (%esp)Behaupte, das hat nicht funktioniert. Eine dezimale 3 ist zwar auf dem Stack, das ist aber keine Fliesskommazahl 3.0. Im schlimmsten Fall hast du die NaN geladen...
So müsste es wie gedacht funktionieren:a: .float 3.0 movl a, %eax pushl %eax flds (%esp)
Erst den Inhalt der Variable a nach eax laden, dann den Inhalt von eax auf den Stack pushen und erst danach mit fld vom Stack holen...
-
.text .globl main main: flds a fadds b fsts a mov a, %eax push %eax push $text call printf push $0 call exit .data text: .string "zahl: %f\n\0" a: .float 1 b: .float 2
Ich danke dir vielmals. Im eax Register stehts schon richtig drin. Das mir printf immer -0,00000 ausgibt ist erstmal nicht so wichtig.
Bisher war ich der Meinung das $ greift auf den Wert und nicht auf die Adresse zu. Erstaunlich das ich mit dieser Einbildung so weit so Fehlerfrei gekommen bin.
Ist für mich nur sehr ungewohnt, weil ja int $0x80 auch den Wert meint und nicht die Adresse dahinter.
Sehr bedauerlich das die GNU ASM Dokus und Tutorials alle viel zu kurz sind.Danke nochmal
-
Viel schlimmer ist jedoch:
Ich finde keine Intel-instruction die mir das Vergleichen zweiter
floating point numbers ermöglicht.
Muss ich nochmal genauer nachgucken.PS: Man merkt - ich habe mich bei der Registrierung verschrieben.
-
fcom und vielleicht noch fstsw und sahf werden wohl die Befehle sein, nach denen du suchst.
Zu deinem Benutzernamen: Schreib mal eine Mail an Marc++us. Wenn er gerade etwas Zeit hat, aendert er vielleicht deinen Benutzernamen.
-
Das mir printf immer -0,00000 ausgibt ist erstmal nicht so wichtig.
Das ist sehr wichtig, denn die printf-Funktion kann meines Wissens keine floats ausgeben, nur doubles - und das hat Auswirkung wie man die Parameter auf dem Stack ablegt. Die 8 Bytes eines doubles muss man unter Beachtung der "Endianesses" auf dem Stack ablegen, ungefähr so:
tmp: .double 0.0 ... ftspl tmp movl (tmp + 4), %eax pushl %eax movl tmp, %eax pushl %eax
Damit wäre eine double-Variable tmp auf dem Stack, etwas unschön gemacht, schöner wäre z.B. so:
fstpl (%esp)
Das war's.
Was in deinem Code-Ausschnitt noch fehlt, ist die Bereinigung vom Stack, machst lauter push, aber kein einziges pop, in dem kurzen Code ist das vielleicht nicht so kritisch, später aber, wenn es umfangreich wird und du dich wunderst, warum bekomme ich ständig Stack-Overflows...
Ansonsten hast du coole Sache gemacht, 1.0 + 2.0 auf Pentium 4 berechnet, warum auch nicht, weiter so