Hallo zusammen, ich spiele mit dem ARM-Assembler unter DAVE4 für einen Cortex M4f. Ich versuche mit VMOV eine Konstante zu laden, dabei stoße ich auf folgendes Problem: VMOV.F32 s1, #0.25 // funktioniert! VMOV.F32 s1, #0.26 // funktioniert nicht! Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32 nachbilden lässt. Gibt es einen Trick, mit dem man dem Assembler mitteilt, dass der die nächstmögliche F32-Darstellung der Zahl verwendet? Ich habe das Manual so interpretiert, dass er das auch ohne zusätzliche Anweisung machen würde, tut er aber wohl nicht... Also habe ich habe nach einer Art Rundungsderektive gesucht, bin aber nur auf die gleiche Frage gestoßen. Wie ist der Trick hierfür? Gruß Stephan
Eine immer wieder gern gestellte Frage, aber immer noch sinnvoll: Was genau heisst denn, das es "nicht funktioniert"?
Stephan schrieb: > Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32 > nachbilden lässt. Kleine Pingeligkeit: Es lässt sich überhaupt nicht mit Binär-Floating-Point darstellen, egal wie viele Bits ;-) Ist so wie 1/3 sich nicht mit Dezimalzahlen darstellen lässt, egal wie viele...
Also, lautet die Analyse so: 1. Die Zahl ist in den Beschränkungen des Assemblers nicht als Float darstellbar. +/– n * 2–r,where n and r are integers, 16 <= n <= 31, 0 <= r <= 7 2. Der C-Preprozessor ist zwar verwendbar, kann aber nicht mit Floats umgehen. Daraus folgt, dass es auch kein Macro geben kann, dass diese Rundung durchführt. Das ist also vermutlich unter "funktioniert nicht" zu verstehen. Man könnte also allenfalls (das ist nur so eine Idee) der Nachkommateil als Integer darstellen und damit was basteln. D.h. aus 0.26 die Zahl 26 machen und dem Macro noch den Faktor mitgeben (also 100). Die nächstliegenden Zweierpotenzen sind 64 und 128 - für 0.01; den Teil der 1/100 entsprich. 1/64 = 0.0156 1/128 = 0.00781 Die Differenz zu 0.01 ist bei 1/128 geringer. Also nimmt man das. Voilà. Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem enspricht, was man "programmieren" nennt, erspare ich mir.
Dr. Sommer schrieb: > Stephan schrieb: >> Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32 >> nachbilden lässt. > Kleine Pingeligkeit: Es lässt sich überhaupt nicht mit > Binär-Floating-Point darstellen, egal wie viele Bits ;-) Ist so wie 1/3 > sich nicht mit Dezimalzahlen darstellen lässt, egal wie viele... Widerspruch: 1/4, 1/2, 1.0 u.v.m. lassen sich sowohl im Dezimalsystem als auch im IEEE-Float32-Format mit einer endlichen Anzahl an Stellen exakt abbilden. :-) Das Problem ist, dass der Assembler die Befehlszeile nicht akzeptiert und den Fehler "garbage following instruction" wirft. Im ARM-Infocenter für den ARM Compiler habe ich die Fußnote "Any number that can be expressed as +/-n * 2-r, where n and r are integers, 16 <= n <= 31, 0 <= r <= 7." gefunden. Das bestätigt schonmal die Annahme bzgl. der Ursache... Gibt es bei den GCC keine Hilfsfunktion, die die (fehlerträchtige) Konvertierung/Rundung einer Zahl in eine vom Assembler akzeptierte Hex/Bin-Darstellung übernimmt? Der GCC-C-Compiler muss das bei "float32_t K = 0.26" schließlich auch vornehmen. Stephan
"Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem enspricht, was man "programmieren" nennt, erspare ich mir." Du tust gut daran! Davon auszugehen, dass für ein Standardprobleme, die sehr fehlerträchtig sein können, die Lösung nicht bereits in dem verwendeten Werkzeug vorhanden ist, führt oft zu massiven Fehlern und stellt einen nicht unerheblichen Zeitaufwand dar.
Stephan schrieb: > "Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem > enspricht, was man "programmieren" nennt, erspare ich mir." > > Du tust gut daran! Davon auszugehen, dass für ein Standardprobleme, die > sehr fehlerträchtig sein können, die Lösung nicht bereits in dem > verwendeten Werkzeug vorhanden ist, führt oft zu massiven Fehlern und > stellt einen nicht unerheblichen Zeitaufwand dar. Ja, ja, Meister. Du hast nur gefragt, weil Du Langeweile hattest. Schon klar.
Für alle, die diesen Beitrag irgendwann mal ausgraben: Const_1: .float 0.26 ... VLDR.32 s1, Const_1 Hier wird der Wert der Konstante zwar aus dem Speicher geladen und nicht als Immediate, dafür bleibt der Quellcode gut lesbar; man muss nicht mit den Hex-Darstellungen der Floats hantieren. http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/CHDICEDI.html Der Assembler des ARM-Toolchains für NEON kennt eine gleichnamige Pseudo-Anweisung VLDR.32 s0,=const die (falls möglich) in eine einzelne VMOV-Anweisung übersetzt wird. http://infocenter.arm.com/help/topic/com.arm.doc.dui0489f/CIHGGHHA.html Der GCC-Assembler von DAVE4 scheint dies nicht zu tun. Unabhägig vom Wert der Konstanten wurde bei mir VLDR.32 s0,=const (Quelltext) stets in vldr s0, [r0] übersetzt. Evtl. hilft es jemand... Gruß Stephan
Danke Stefan, vor vielen Jahren habe ich die FPU auch zum ersten mal eingesetzt und muste auch feststellen, dass nicht jede Zahl als direkte Angabe funktioniert. Mann muss nur in der Dokumentation bei ARM nachlesen, dann sieht man sofort, das es sehr eingeschränkt ist. Also bleibt nur das laden eines Prozessorregister in ein FPU-Register oder die elegantere Art, die Stefan zeigt übrig. Das indirekte laden PC+rel ist durchaus sehr gut. Nur nicht vergessen, irgendwo müssen die Daten dann auch im ROM sein. deshalb am Ende der Routine noch ein .LTORG setzen, ab da werden dann die Daten gespeichert. Übrigens finde ich die FPU sehr gelungen, auch für DSP übrigens spitze zu verwenden. Werde mal diese Woche die FPU eines CM7 von ST mit 64 Bit ausprobieren. Mal sehen wie schnell die ist? Gruß Sascha FPU in Assembler ist einfach wie ein Gedicht....
Sorry Stephan, ist keine Absicht habe deinen Namen falsch geschrieben.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.