fb18.de
/ Diplom Informatik
/ Unterbereich Grundstudium
/ Technische Informatik
t3 aufgabe 13
moin moin
also ich bin beim loesen der aufgabe auf ein kleines mysterium getroffen…
ich kann meine assembler routine aufrufen und bekomme ein ergebnis mit dem ich durchaus zufrieden bin, wenn ich allerdings die routine ein zweitesmal aufrufe kriege ich einen segmentation fault… grund dafuer ist d_1000… die liefert mir in %o0 (wo eigentlich die addresse des arrays drinstehen sollte) eine 0…
die frage ist nun habt ihr das problem auch… ist d_1000 murks oder liegt es mal wieder an mir?
mit ein bischen rumbasteln hab ich es glaube ich geschafft mir die adresse zwischenzuspeichern und wieder herzustellen
vielleciht kann mir ja jemand sagen ob die ergebnisse richtig sind?
fuer abrunden: 000000509.016496591050668
-unendlich:000000505.633052994266734
+unendlich:000000505.633052994301693
Warst du der, der heute im RZ da shcon am basteln war? Anosnsten habe ich soweit beobachtet dass d_1000 zwar nicht immer dieselbe Adresse abgibt aber 0 kam nicht vor. Hat jemand ähnliches beobachten können?
ja ich gestehe… ich habe gebastelt ;)
printf("%d\n",d_1000());
printf("%d\n",d_1000());
printf("%d\n",d_1000());
ergibt:
135064
-13368684
-13368684
ist das so geplant?
das führt leider auch zu nem segfault wenn mans mehrfach aufruft…
rzdspc3$ a.out
Rundungsmodus: 0
000000508.633052994286004
Rundungsmodus: 1
000000508.633052994266734
Rundungsmodus: 2
000000508.633052994301693
Rundungsmodus: 3
000000508.633052994266734
schade.. hab ein etwas anderes ergebnis (ob die ergebnisse irgendwas mit der realität zu tun haben weiss ich leider nicht) *g*
ist nun der erste rundungsmodus den wir verwenden sollen = 0 oder = 1 ?
rzdspc3$ a.out
Rundungsmodus: 1
000000508.633052994266734
Rundungsmodus: 3
000000508.633052994266734
Das macht durchaus Sinn, falls die Zahlen alle positiv sind. Dann ist zur Null Runden und Richtung -unendlich Runden ja äquivalent.
ist nun der erste rundungsmodus den wir verwenden sollen = 0 oder = 1 ?
Der auf dem Aufgabenzettel mit "1." betitelte Modus ist der Modus 0. Der Modus 1 (zur Null runden) soll nicht berücksichtigt werden, wahrscheinlich gerade weil es in diesem Fall kein anderes Ergebnis als Rundungsmodus 3 gibt.
jetzt bin ich total verwirrt… das mein abrunden ergebnis rausfällt ist mir ja schon aufgefallen… aber die anderen beiden sind ja schön dicht beisammen… nun frage ich mich warum brokkoli bei 2 zahlen genau um 3.0 versetzte ergebnisse hat… ich glaube ich muss mir das programm am freitag noch mal genau anschauen
@ fred …was ist jetzt eigentlich mit dem d_1000.o … ist das gewollt, dass das nicht geht oder ist da inzwischen mal was passiert?
Also mein erster test, der mehrfach d_1000 aufruft, gab keine Segfaults soweit von sich
ahh mein fehler …
ich bekomm auch 508. … fuer die beiden unendlich rundungen raus
abtippen will gelernt sein… grml
Also mein erster test, der mehrfach d_1000 aufruft, gab keine Segfaults soweit von sich
hm hast du auch mal versucht auf die speicheradresse zuzugreifen die die funktion zurückgibt?
Also mein erster test, der mehrfach d_1000 aufruft, gab keine Segfaults soweit von sich
hm hast du auch mal versucht auf die speicheradresse zuzugreifen die die funktion zurückgibt?
Jup
Mir ist irgendwie noch nicht ganz klar wie das jetzt aufgebaut werden soll. Also ist d_1000.o mein Hauptprogramm und ich soll das Unterprogramm in Assembler schreiben, dass die Summe des Arrays in bestimmten Rundungsmodi ausgibt? Wenn dem so ist was muss ich denn bei
.global hinschreiben, d.h. wie muss meine Funktion öffentlich gemacht werden damit d_1000.o auch sein Array und die Größe an mein Unterprogramm weitergibt? Oder habe ich da etwas grundsätzlich falsch verstanden?
Mir ist irgendwie noch nicht ganz klar wie das jetzt aufgebaut werden soll. Also ist d_1000.o mein Hauptprogramm und ich soll das Unterprogramm in Assembler schreiben, dass die Summe des Arrays in bestimmten Rundungsmodi ausgibt?
Nein, das Hauptprogramm musst du selber schrieben. d_1000.o enthaelt eine Routine d_1000 die du per call aufrufen kannst und nach deren Aufruf hast du die Adresse des Arrays in o0 und die Anzahl der Zahlen in o2.
Wenn ich call d_1000 benutze kommt:
Undefined first referenced
symbol in file
main /local/SUNWspro/prod/lib/crt1.o
d_1000 rundung.o
ld: fatal: Symbol referencing errors. No output written to a.out
is doch richtig, dass man anschließend die beiden per
cc rundung.s d_1000.o kompiliert oder?
du musst d_1000.o bei der Kompilation mit angeben, also
cc main.c rundung.s d_1000.o
wenn die C/Assembler-Datei so heissen
Also d_1000.o habe ich ja mit angegeben siehe oben. Aber wieso denn
cc main.c rundung.s d_1000.o
Ich meine was ist denn das main.c? *kopfkratz* rundung.s und d_1000.o müssten doch reichen?
wenn du ein c programm zum starten hast, was dann deine assemblerroutine aufruft?
ah Ok. Ich dachte man kann auch direkt die Assemblerroutine starten.
Also ich habe jetzt eine main.c die die Assemblerrountine rundung.s aufruft, die wiederum per "call d_1000" d_1000 aufruft.
Leider klappt das immernoch nicht
ich habe jetzt per cc main.c rundung.s d_1000.o kompiliert und kriege den Fehler:
main.c:
rundung.s:
Undefined first referenced
symbol in file
d_1000 rundung.o
ld: fatal: Symbol referencing errors. No output written to a.out
Also erkennt er den call d_1000 irgendwie nicht. Muss ich d_1000.o noch irgendwie in der Assembler-Datei "bekannt" machen oder wo liegt der Fehler?.
Muss ich d_1000.o noch irgendwie in der Assembler-Datei "bekannt" machen oder wo liegt der Fehler?.
.global d_1000
Also der Fehler besteht weiterhin. .global ist doch auch dazu da um eine "Prozedur" in der selben Datei sichtbar zu machen oder nicht?
–> d_1000 ist aber doch in der Datei d_1000.o . Wenn ich jetzt also .global d_1000 mache dann müsste ich doch zusätzliche noch eine Prozedur wie beispielsweise:
d_1000:
mov….
cmp ….
jmp….
in meiner ASM Datei machen oder nicht?
Das will ich aber ja nicht, es soll ja die Prozedur in d_1000.o ausgeführt werden. Ich hoffe man konnte meinem verständnisproblem folgen und bedanke mich schonmal für die bisher und im folgenden getätigten Mühen :).
.global ist doch auch dazu da um eine "Prozedur" in der selben Datei sichtbar zu machen oder nicht?
Beides. Du verwendest ja auch beispielsweise ".global printf", um printf verwenden zu können.
Ah Ok. Obwohl ich printf bisher nicht global machen musste damit es funktioniert.
Hier mal ein Ausschnitt aus meiner rundung.s:
.section ".text"
.align 4
.global rundung, d_1000
rundung:
call d_1000
nop
usw….
Fehlermeldung beim kompilieren:
Undefined first referenced
symbol in file
d_1000 rundung.o
ld: fatal: Symbol referencing errors. No output written to a.out
Ich bin offenkundig ratlos =/
.global ist doch auch dazu da um eine "Prozedur" in der selben Datei sichtbar zu machen oder nicht?
Beides. Du verwendest ja auch beispielsweise ".global printf", um printf verwenden zu können.
also ich weiss nich… in meiner assemblerdatei steht weder was von .global printf noch von .global d_1000… aber trotzdem kompiliert der ohne probleme..
Ich habe die Rundungsmethoden noch nicht verstanden. Ich weiss nicht wann ich auf wieviel Stellen genau runden soll. Die Fliesskommazahlen sind in doppelter Genauigkeit, also 15 Stellen hinter dem Komma. Wenn ich die addiere, kommen wieder Zahlen mit 15stelliger Genauigkeit heraus. Und das Ergebnis soll auch auf 15 Stellen hinter dem Komma angegeben werden. Ich sehe im Moment keinen Grund zum Runden.
Zitat:
.global ist doch auch dazu da um eine "Prozedur" in der selben Datei sichtbar zu machen oder nicht?
Beides. Du verwendest ja auch beispielsweise ".global printf", um printf verwenden zu können.
Das .global kommt doch in die Übersetzungseinheit die das Symbol auch definiert. Also in diesem Fall in die C-Bibliothek, nicht beim Aufrufer. Wenn in der aufrufenden Objekt-Datei dann soetwas wie "call printf" steht, wird das Symbol einfach als Undefiniert vermerkt und automatisch mit globaler Bindung versehen, was anderes macht ja auch keinen Sinn wenn es nicht lokal definiert wird. Oder täusche ich mich?
Brokkoli: Ich habe auch deine Ergebnisse.
–
EP
Ich sehe im Moment keinen Grund zum Runden.
Beispiel mit Dezimalzahlen: Angenommen das imaginäre Zahlenformat hat 3 Stellen hinterm Komma + 2-stelligen Exponent. Nun addieren wir mal 123 und 989.
989 = 0.989e03
123 = 0.123e03
Addiert ergibt sich
123 + 989 = 1112 = 1.112e03
Da ist nun eine Kommastelle zuviel, wir müssen das auf 3 Stellen hinterm Komma bringen, die 1 vorm Komma kann unser Format nämlich nicht speichern. Nun können wir 0.111e04 oder 0.112e04 speichern, je nachdem, wie gerundet wird.
Dasselbe Problem ergibt sich verschärft bei Fließkommazahlen weil wir da 2er-Potenzen haben.
Also ich finde den Fehler einfach nicht….ich mache mal ein bischen mehr Quelltext vielleicht sieht ihn jemand:
(Habe das Programm jetzt soweit wie möglich minimiert um andere Fehler auszuschliessen)
main.c:
#include <stdio.h>
void rundung();
int main(int anzahl)
{
rundung();
return 0;
}
ruft erstmal die Rundungsroutine auf:
rundung.s:
.section ".text"
.align 4
.global rundung
rundung:
call d_1000
nop
jmp %i7+8
restore
und dann kompiliere ich cc main.c rundung.s d_1000.o
und kriege:
main.c:
wayne2.s:
Undefined first referenced
symbol in file
d_1000 wayne2.o
ld: fatal: Symbol referencing errors. No output written to a.out
Kein Plan wieso es nicht klappt. I
main.c:
wayne2.s:
Undefined first referenced
symbol in file
d_1000 wayne2.o
ld: fatal: Symbol referencing errors. No output written to a.out
Kein Plan wieso es nicht klappt. I
Der Compiler sagt, dass d_1000 nicht definiert ist. Eine Definition war auch nicht im Quelltext zu sehen. Das ist wohl der Fehler..
Wenn etwas referenziert wird, muss es erst deklariert und definiert sein.
Also so wie ich das bisher verstanden habe sollte er d_1000 aus der d_1000.o ziehen, die ich beim kompilieren mit angegeben habe. Auf dem Aufgabenblatt steht ja dann dass das Array anschließend in %o0 und die Größe in %o2 landet.
Kein Plan wieso es nicht klappt.
Ich habe jetzt mal ein eigenes Grundgerüst gebaut:
.section ".text"
.align 8
.skip 16
.global array_generieren
array_generieren:
save %sp,-112, %sp
call d_1000
nop
ret
restore
Damit funktioniert es wunderbar, es muss also an was anderem liegen. Ist die d_1000.o auch im selben Verzeichnis? Ist vielleicht beim Herunterladen ein Fehler passiert? Die Datei sollte 884 Bytes gross sein, jedenfalls ist sie das bei mir.
Die MD5 Summe ist 41d26d18a4eb1ce3657a767ea5bca28a
Hmmm meine Datei war nur 600 Byte groß :/. Jetzt geht's auch….keine Ahnung was da beim downloaden falsch gelaufen ist nun funktioniert es endlich auch….DANKE!
Jo, kein Problem. Hier als Vergleich die Ergebnisse meiner Lösung:
rzdspc3$ dos2unix array.s s.s
could not open /dev/kbd to get keyboard type US keyboard assumed
could not get keyboard type US keyboard assumed
rzdspc3$ cc main.c s.s d_1000.o
main.c:
s.s:
rzdspc3$ a.out
round to nearest : 000000508.633052994286004
round to zero : 000000508.633052994266734
round to +infinity: 000000508.633052994301693
round to -infinity: 000000508.633052994266734
rzdspc3$
kurze Frage zum Zugriff auf das Double-Array. Das läuft doch per ldd und die Folge-Elemente sind dann 8 weiter oder? 1. [%o0+0]
2. [%o0+8] 3. [%o0+16] usw?
Das läuft doch per ldd und die Folge-Elemente sind dann 8 weiter oder?
Richtig!
muss ich bei der addition der elemente irgendwas beachten ich kriege nämlich riesige werte raus wenn ich ganz normal die 1024 elemente aufaddiere
muss ich bei der addition der elemente irgendwas beachten ich kriege nämlich riesige werte raus wenn ich ganz normal die 1024 elemente aufaddiere
Auf Fließkommazahlenaddition hast du schon geachtet? ;) und dass es double-Werte sind?
muss ich bei der addition der elemente irgendwas beachten ich kriege nämlich riesige werte raus wenn ich ganz normal die 1024 elemente aufaddiere
Du musst immer 8 Bytes weitergehen im Array pro Element. Wenn Du nur 2 oder 4 Bytes weitergehst kommen tatsächlich Zahlen raus, die über mehrere Bildschirmzeilen gehen. Lags daran?
nein ich hab ganz normal per add addiert.(8 weitergegangen bin ich)
Also die Fließkommazahlenaddition nicht beachtet.
irgendwie muss das also mit fadd laufen stimmts? Ich weiss allerdings nicht wie .
irgendwie muss das also mit fadd laufen stimmts? Ich weiss allerdings nicht wie.
Du musst zunächst einmal einen Akkumulator auf 0 setzen, da bietet sich z.B. das Registerpaar %f0/%f1 an. In diesem Registerpaar addierst Du dann die Elemente auf. Dazu musst Du immer ein Element per ldd aus dem Array in ein Registerpaar laden, z.B. %f2/%f3, und dann per faddd (ja, dreimal der Buchstabe d) auf %f0/%f1 draufaddieren… und das halt über das ganze Array.
Könnte es sein, dass es so viele Probleme bzgl. der d_1000 gibt, weil der Webserver die Datei fälschlicherweise als text/plain deklariert und dann manche Browser/Betriebssysteme die Zeilenumbrüche, die in Wirklichkeit ja keine sind, da es sich um eine Binärdatei handelt, verwurschteln? Bei uns hat's funktioniert, wir haben aber auch mit wget direkt auf der rzdpsc3 gearbeitet.
Den Effekt, dass d_1000 beim wiederholten Aufruf (im selben Programm versteht sich) andere Ergebnisse liefert, mussten wir allerdings auch feststellen. Woran kann das liegen?
Allerdings zeigt bei uns irgendwie das Aufrufen von fpsetround keine Wirkung (Ergebnis stimmt mit Rundungsmodus 0 überein). Muss man da noch irgendwas beachten oder doch lieber %fsr manuell bearbeiten?
Allerdings zeigt bei uns irgendwie das Aufrufen von fpsetround keine Wirkung (Ergebnis stimmt mit Rundungsmodus 0 überein). Muss man da noch irgendwas beachten oder doch lieber %fsr manuell bearbeiten?
also ich habe nichts besonderes gemacht..
den modus (0-3) in o0 und dann call fpsetround funktioniert wunderbar..
warum kommen eigentlich wenn man da fehler macht unter umständen zahlen heraus die über mehrere zeilen auf dem monitor gehen? so eine genauigkeit hat doch double oder was immer garnicht.. (nicht dass es für die aufgabe wichtig wäre, aber es interessiert mich halt)
Ich hab das hier raus 000000508.632812500058208
knapp daneben wies aussieht.
den modus (0-3) in o0 und dann call fpsetround funktioniert wunderbar..
Argh. Sieht wohl so aus, dass der Rundungsmodus nach einem Prozedur-Aufruf immer wieder zurückgesetzt wird. Das muss einem ja gesagt werden. Jetzt klappt es (wir hatten vorher erst den Rundungsmodus gesetzt, dann d_1000 aufgerufen).
warum kommen eigentlich wenn man da fehler macht unter umständen zahlen heraus die über mehrere zeilen auf dem monitor gehen? so eine genauigkeit hat doch double oder was immer garnicht.. (nicht dass es für die aufgabe wichtig wäre, aber es interessiert mich halt)
Ich _vermute_, dass dies an der Dezimal-Darstellung liegt, also nur durch die Umwandlung von Binär auf Dezimal verursacht wird.
Was meinst du mit "wenn man da fehler macht"? Also hier kommt da immer so eine Mörder-Zahl raus, wenn d_1000 mehrmals hintereinander aufgerufen wird.
also ich meine wenn ich da etwas drauf addiere was z.b. kein double ist.. ein int oder so - also klar das kann dann ja wegen der bytedarstellung kein vernünftiges ergebnis geben, aber sollte dann nicht einfach NaN oder so herauskommen? bei mir ist das ergebnis dagegen einie zahl mit mehreren hundert stellen..
also ich meine wenn ich da etwas drauf addiere was z.b. kein double ist.. ein int oder so - also klar das kann dann ja wegen der bytedarstellung kein vernünftiges ergebnis geben, aber sollte dann nicht einfach NaN oder so herauskommen?
Nein, die FPU kann ja nicht wissen, dass die paar Bytes eigentlich nicht als double vom Programmierer gedacht waren.
bei mir ist das ergebnis dagegen einie zahl mit mehreren hundert stellen..
Wobei Du natürlich völlig recht hast, das sind nicht alles signifikante Stellen. Und wie jemand anders schon schreib ist das in der Umwandlung Binär -> Dezimal begründet. Wenn man die Zahl binär ausgeben würde, dann hätte sie 52 signifikante Bits gefolgt von ziemlich vielen Nullen… kannst Du ja mal ausprobieren per Hand umzurechnen [img]
http://www.fb18.de/gfx/25.gif[/img]
ich bräuchte nochmal einen rat bei fpsetround
wenn ich fpsetround nicht benutze, bekomme ich das richtige ergebnis (also das aus dem forum). schieb ich aber 0 in o0 und mach call fpsetround, bekomme ich: 000000001.236950143171700
weiss jemand was ich falsch mache?
du verwendest o0 noch woanders? *g*
nö, die adresse des arrays hab ich vorher in l1 getan und zum aufaddieren verwende ich auch nur l1.
weiss jemand was ich falsch mache?
Kannst Du mal ein paar relevante Assemblerzeilen posten?
call d_1000
nop
mov %o0, %l1
mov 0, %o0
call fpsetround
nop
ldd [%l1],%f0
wenn ich die zeile mit dem call rausnehme, stimmt das ergebnis.
Du hast vergessen o2 zu sichern, das wird wahrscheinlich durch das setround zerschossen.
jo, vielen dank. jetzt läufts
Ich habe jetzt auch das Problem mit dem Segmentation Fault, wenn ich meine Methode zum zweiten mal aufrufe.
Wenn ich nur eine Fliesskommazahl berechne, kommt das richtige Ergebnis heraus, egal welcher Rundungsmodus. Aber wenn ich alle 3 hintereinander berechnen möchte, und dabei jedes mal wieder d_1000 aufrufe, zeigt er nur das erste Ergebnis an und dann den Segmentation Fault.
printf("Runden zum naechsten: %025.15f\n", floatadd(0));
printf("Runden nach +unendlich: %025.15f\n", floatadd(2));
printf("Runden nach -unendlich: %025.15f\n", floatadd(3));
In floatadd wird halt immer am Anfang d_1000 aufgerufen.
Gibt es dafür schon eine Lösung?
In floatadd wird halt immer am Anfang d_1000 aufgerufen.
Gibt es dafür schon eine Lösung?
Am naheliegendsten ist es doch, seine Lösung so umzubauen, dass d_1000 eben nicht mehrfach aufgerufen werden muss. Ich weiss leider nicht, was die Routine genau macht, aber falls da dynamisch ein neues Array erzeugt wird wäre es sowieso aus programmiertechnischer Sicht Unsinn, sich mehrmals das gleiche Array zu erzeugen.
Ich sehe da momentan zwei Möglichkeiten:
1. Eine Routine schreiben, welche d_1000 einmalig aufruft und dabei beide Werte (Adresse und Länge des Arrays) an C zurückgibt. Mögliche Signaturen, die mir dafür im Kopf herumschwirren, wären:
void irgendwas_sinnvolles(char **, int *);
int irgendwas_sinnvolles(char **);
char *irgendwas_sinnvolles(int *);
Da Du ja nur einen Wert nach C zurückgeben kannst musst Du mindestens einen (anderen) Wert per Zeiger auf eine entsprechende Variable als Aufrufparameter angeben.
2. Eine Routine schreiben, welche d_1000 aufruft und die beiden Parameter des Arrays "intern" im Datensegment speichert, z.B.
void initialisiere_array();
Die Routine, welche dann über das Array summieren will, holt sich die entsprechenden Paramter dann aus dem Datensegment. Da kann man natürlich noch eine Prüfung einbauen, ob initialisiere_array bereits aufgerufen wurde und dann ggf. entsprechend darauf reagieren.
Ich denke diese Lösung ist vor allem für diejenigen Leute einfacher, welche noch nicht so gut mit Zeigern umgehen können. Diesen Leuten sei übrigens
http://cslibrary.stanford.edu/104/ empfohlen.
Okay, zu der Datensegment-sache habe ich noch mal ne Frage.
Ich habe mir jetzt mal eine Testroutine geschrieben, die mir beim Aufruf von intarray() und test() die Länge des Arrays zurückgeben sollte.
Die sieht so aus:
.section "data"
.align 4
anz: .word 0
.section "text"
.align 4
.global intarray
.type intarray,#function
intarray:
save %sp, -128, %sp
call d_1000 ! d_1000 aufrufen
nop
set anz, %o1
st %o2, [%o1]
jmp %i7+8
restore
.global test
.type test,#function
test:
save %sp, -128, %sp
set anz, %o1
ld [%o1], %o0
jmp %i7+8
restore
Leider bekomme ich immer nur einen "Segmentation Fault"
Habe ich mit dem Datasegment irgendetwas falsch verstanden?
Jan
.section "data"
.section "text"
Du hast den Punkt vergessen. Die Sektionen heissen ".data" und ".text".
Du hast den Punkt vergessen. Die Sektionen heissen ".data" und ".text".
Juchu! Jetzt funktionierts. Danke.
Eigentlich ein peinlicher Fehler. Mal wieder typischer Fall von "kann nicht abschreiben" :)
JAn
Ich habe irgendwie ein leicht falsches Ergebnis:
000000508.632812500058208
weiss aber nicht was falsch ist . Bei den F -Registern übergibt man doch so eine 0 oder?
st %g0,[%o1]
ld [%o1], %f2
Und wenn ich dann das fertige Ergebnis an das %o1 übergebe um es per printf auszugeben so oder?
st %f2 , [%i1]
ld [%i1], %o1
Oder ist da irgendwo der Fehler?
Du löschst nur die oberen 32 Bit des Akkumulators, die unteren 32 Bit haben noch einen zufälligen Wert und verfälschen daher das Ergebnis leicht. Verwende statt des ld ein ldd - natürlich musst Du dann vorher aber auch zwei aufeinanderfolgende Worte im Speicher auf 0 setzen statt nur einem.
Beim Ausgeben musst Du analog std verwenden und dann auch zwei Register füllen.
weiss aber nicht was falsch ist . Bei den F -Registern übergibt man doch so eine 0 oder?
st %g0,[%o1]
ld [%o1], %f2
Wie schon erwähnt kann man einfach eine zweite "Null" in %o1+5 schreiben. Aber das geht so nur mit der 0 und nicht mit andere Werten. Deshalb schlage ich einen etwas allgemeineren Weg vor:
st %g0,[%o1]
ld [%o1], %f2
fitod %f2, %f2
Damit macht er dir aus "was auch immer für einen Integer" die korrekte Double-FP-Zahl. Also auch mit der 0.
Jan
Wie schon erwähnt kann man einfach eine zweite "Null" in %o1+5 schreiben.
ich würd +4 empfehlen [img]
http://www.fb18.de/gfx/28.gif[/img]
Wie schon erwähnt kann man einfach eine zweite "Null" in %o1+5 schreiben.
Wieso +5 ?
st %g0,[%o1]
ld [%o1], %f2
fitod %f2, %f2
Damit macht er dir aus "was auch immer für einen Integer" die korrekte Double-FP-Zahl. Also auch mit der 0.
Sehr schön erklärt.
Meine Lösung sah übrigens so aus:
subd %f0, %f0, %f0
Allerdings bin ich mir nicht 100% sicher, ob das auch mit NaN und den unendlichen Werten funktioniert.
Wie schon erwähnt kann man einfach eine zweite "Null" in %o1+5 schreiben.
Wieso +5 ?
Ups, Tippfehler. Sollte eine +4 sein.
Meine Lösung sah übrigens so aus:
subd %f0, %f0, %f0
Allerdings bin ich mir nicht 100% sicher, ob das auch mit NaN und den unendlichen Werten funktioniert.
also so wie ich NaN und unendlich verstanden habe sollte es nicht funktionieren ;)
Nachdem ich jetzt einige Stunden damit verbracht habe,
einen Fehler in meiner Lösung zu finden, möchte ich
eine (zumindest für mich) wichtige Erkenntnis weitergeben:
Wenn das Programm noch Fehler zu haben scheint, ist es
KEINE gute Idee, Debugging-Ausgaben zwischen den Berechnungen
mit printf zu machen ohne vorher die f-Register zu sichern.
printf scheint die nämlich zu verwenden und somit
die Ergebnisse völlig unsinnig zu machen (was ja eigentlich
auch klar ist).
Ich hoffe, das erspart jemand anderem eine ähnliche
Suchaktion. [img]
http://www.fb18.de/gfx/28.gif[/img]
(Bei mir schien am Anfang ein Fehler drin gewesen zu sein,
nach dessen Behebung ich aber die Debug-Meldungen noch
nicht entfernt hab, sodass das Programm dann erst nach dem
Entfernen der Debug-Meldungen funktionierte)
Kann mir jemand sagen wie man anschließend den Wert aus dem Floating-Point register in %o1 und %o2 bekommt? Da müssen sie ja wenn ich mich recht entsinne rein damit man es per printf behandeln kann.
Irgendwie klappt das nicht.
mit std speicherst du einen double wert aus 2fp regs in 8 bytes im speicher
und die kannst du dann mit 2x ld in die "normalen" register laden
…und die kannst du dann mit 2x ld in die "normalen" register laden
Dürfte es nicht auch mit
ldd [Adresse], %o1
funktionieren?
Soweit ich ldd verstanden habe nimmt er immer das angegebene, "gerade" Register und ein Register weiter.
ldd funktioniert nur mit den f-registern
ldd funktioniert auch mit den "normalen" Registern. Aber es muss als Parameter immer ein gerades Register erhalten und benutzt dann das nächste ungerade dazu. Da 1 bekanntlich ungerade ist, funktioniert "ldd [Adresse], %o1" also nicht, "ldd [Adresse], %o2" würde hingegen schon funktionieren. Man könnte z.B. %o1 dann benutzen um den aktuellen Rundungsmodus mit ausgeben zu lassen [img]
http://www.fb18.de/gfx/25.gif[/img]
oh ok hab ich mich wohl getäuscht *g*
Dürfte es nicht auch mit ldd [Adresse], %o1
funktionieren?
Soweit ich ldd verstanden habe nimmt er immer das angegebene, "gerade" Register und ein Register weiter.
Da habe ich mir ja irgendwie selbst in den Fuß geschossen… 1 ist recht ungerade. Also muss man natürlich zweimal ld benutzen um die double-FP-Zahl in %o1 und %o2 zu bekommen. :)