fb18.de
/ Bachelorstudieng
/ PM Technische Informatik
Ausführen eines Assemblerprogramms
Ich habe Aufgabe 36 Übungsblatt 10 fehlerfrei assembliert.
Wenn ich es jetzt allerdings mit a.out 170 1 4
aufrufen will, bekomme ich die Fehlermeldung: "Segmentation Fault"
Woran liegt das?
Danke Problem hat sich schon gelöst. =)
a.out 170 1 4
Du parst die Argumente von der Kommandozeile? Ist das auf dem Aufgabenblatt gefordert?
Es ist gefordert dass 2 Bits vertauscht werden sollen und ich woltel über Kommandozeilenparameter steuern, welche Zahl und wlech eBits gesteuert werden sollen.
Aber anscheinend habe ich nicht genaz verstandne, wie man die angegebenen Parameter verarbeitet.
Die Parameter sollen nicht per Kommandozeile, sondern an ein Unterprogramm übergeben werden.
Ja schon klar ich wollte ja nur, dass man die per Kommandozeile eingibt und anschließend ans Unterprogramm weitergibt.
Mal ne Frage:
Wann genau taucht der Fehler "Segmentation Fault" imemr genau auf und wie kann man ihn vermeiden?
! Information für Binder
.global main
.global printf
! Deklaration von Daten
.section ".data"
.align 8
x: .double 0r16.0
fmt:
.ascii "Quadratwurzel von %f\n"
.asciz "mit fsqrtd: %f\n"
! ausführbares Programm
.section ".text"
quadratwurzel:
main:
set fmt, %l0
set x,%l1
ldd [%l1],%f2
fsqrtd %f2, %f4
std %f4, [%l6]
mov %l0, %o0
std %f2, [%l1+8]
ld [%l1+8], %o1
ld [%l1+12], %o2
ld [%l6+8], %o3
ld [%l6+12], %o4
call printf
nop
set 1,%g1
ta 0
Bei dem Programm gibt er mir zum Beispiel so einen Fehler
std %f4, [%l6]
Du benutzt %l6 als Adresse, hast aber nie was vernünftiges reingeschrieben. Also versuchst Du an eine zufällige Adresse zu schreiben, was mit hoher Wahrscheinlichkeit schiefgeht.
std %f4, [%l6]
Schreibt man damit nicht etwas da rein?
Nein. std %f4, [%l6] entspricht folgender Anweisung an den Prozessor:
"Lieber Prozessor! Bitte sei so lieb und lege die aktuellen Werte von %f4 und %f5 hintereinander im Speicher ab. Die Adresse, an der Du 8 freie Bytes dafür finden solltest, findest Du im Register %l6. Vielen Dank und bis bald!"
Ich habe jetzt ein
set x, %l6
davor gesetzt.
Jetzt zeigt er diesen Fehler nicht mehr an aber er macht auch keinerlei Ausgabe.
Woran liegt das denn nun schon wieder?
set x, %l6
std %f4, [%l6]
Okay, Du legst %f4 und %f5 also ab Adresse x ab. Und was machst Du anschließend mit diesen 8 Bytes, nachdem Du sie in den Speicher geschrieben hast? Dass sie nicht in %l6 stehen, ist Dir klar? Da steht weiterhin die Adresse x drin.
Kurzer Update meines Quelltextes:
! Information für Binder
.global main
.global printf
! Deklaration von Daten
.section ".data"
.align 8
x: .double 0r16.0
x2: .double 0r0.0
fmt:
.ascii "Quadratwurzel von %f\n"
.asciz "mit fsqrtd: %f\n"
! ausführbares Programm
.section ".text"
quadratwurzel:
main:
set fmt, %l0
set x,%l1 ! Die gewünschte Zahl ins das Register l1 laden
ldd [%l1],%f2 ! x in %f2, %f3
fsqrtd %f2, %f4 ! Wurzel mit fsqrtd in %f4, %f5
set x2, %l6
std %f4, [%l6] ! (double) wurzel
mov %l0, %o0 ! fmt
std %f2, [%l1+8] ! double x nach l1+8
ld [%l1+8], %o1 ! l1+8 nach o1
ld [%l1+12], %o2 ! l1+12 nach o2
ld [%l6], %o3
ld [%l6+4], %o4
call printf
nop
set 1,%g1
ta 0
Ausgabe:
Quadratwurzel von 16.000000
mit fsqrtd: 16.000000
Das ist schon etwas merkwürdig.^^
Ich zitiere mal nur die relevanten Zeilen:
x: .double 0r16.0
x2: .double 0r0.0
!…
set x,%l1
set x2, %l6
!…
std %f4, [%l6]
std %f2, [%l1+8]
Merkst Du was?
Vielen Dank hab meine Fehler gefunden.
Wenn man den ganzen Tag davor sitzt, kann das echt schonmal passieren, dass mal so eine Banalität übersieht.^^
Mal ne Frage:
Wann genau taucht der Fehler "Segmentation Fault" imemr genau auf und wie kann man ihn vermeiden?
http://en.wikipedia.org/wiki/Segfault
Weiter oben kam ja eine Frage wegen der direkteingabe von Werten ueber die Konsole, was mich auch durchaus interessieren wuerde.
Kann da jemand einfach ein Beispiel zeigen, wie ich bei/nach(?) dem Kompilieren einen Wert uebergeben und wie ich diesen im Programm aufnehmen kann?
Wuerde das Ausprobieren ja auch vereinfachen, wenn ich nicht fuer jeden Wert erst im Quelltext herumscrollen, aendern, abspeichern, neu kompilieren usw. muss.
Die Kommandozeilenargumente werden an den Leerzeichen getrennt und dann irgendwo im Speicher abgelegt. Dann wird ein Array angelegt, dass die Startadressen dieser Argumente speichert. Die Startadresse dieses Arrays wiederum steht innerhalb von main in %o1 bzw. in %i1 (falls Du in ein save verwendest).
Nach dem Prinzip hab ich das ja probiert aber hat nicht so ganz funktioniert wie ich wollte aber naja muss ich mri noch mal in RUhe angucken.
Vllt kann mri währenddessen heir jemand weiter helfen, stehe irgendwie gerade auf einem Schlauch und finde den Fehler nicht…
! Information für Binder
.global main
.global printf
! Deklaration von Daten
.section ".data"
.align 8
x: .double 0r16.0
x2: .double 0r0.0
x3: .double 0r0.0
x4: .double 0r2.0
fmt:
.ascii "Quadratwurzel von %f\n"
.ascii "mit fsqrtd: %f\n"
.asciz "mit Newton-Raphson: %f\n"
! ausführbares Programm
.section ".text"
quadratwurzel:
save %sp, -96, %sp
ldd [%i0], %f8 ! x ins f8 und f9
set x4, %l6
ldd [%l6], %f16 ! 2.0 in %f16, %f17
cmp %i0, 0 ! Wenn kleiner denn -1 zurueckgeben
bl kleiner
nop
cmp %i0, 0 ! Wenn 0 denn 0 zurueckgeben
be null
nop
mov %i0, %l0
ldd [%l0], %f10 ! f10 und f11 fuer XALT
fdivd %f10, %f16, %f10 ! XALT = x / 2
mov %l0, %l2
ldd [%l2], %f12 ! f12 und f13 fuer XNEU
mov %i0, %l4 ! XNEU = XALT
ldd[%l4], %f14 ! Hilfsspeicher f14 und f15 fuer x / XALT
fdivd %f14, %f10, %f14 ! h = x / XALT
faddd %f12, %f14, %f12 ! XNEU = (XALT + x/XALT)
fdivd %f12, %f16, %f12 ! XNEU = (XALT + x/XALT) / 2.0
cmp %l0, %l2 ! Wenn die gleich sind gehe zum Ende
be ende
nop
schleife:
mov %l2, %l0 ! XALT = XNEU
mov %l0, %l2 ! XNEU = XALT
mov %i0, %l4 ! x ins HIlfsspeicher
fdivd %f14, %f10, %f14 ! h = x / XALT
faddd %f12, %f14, %f12 ! XNEU = (XALT + x/XALT)
fdivd %f12, %f16, %f12 ! XNEU = (XALT + x/XALT) / 2.0
cmp %l0, %l2 ! Wenn die ungleich sind, wiederhole schleife
bne schleife
nop
ende:
std %f12, [%l4] ! Ergebnis ins o0 und o1
ld [%l4], %o0
ld [%l4+4], %o1
jmp %i7+8
restore
kleiner: ! -1 Wenn x kleiner 0
mov -1, %o0
jmp %i7+8
restore
null: ! 0 wenn x 0 ist
mov 0, %o0
jmp %i7+8
restore
main:
set x,%l1 ! Die gewünschte Zahl ins das Register l1 laden
ldd [%l1],%f2 ! x in %f2, %f3
fsqrtd %f2, %f4 ! Wurzel mit fsqrtd in %f4, %f5
set x2, %l6
std %f4, [%l6] ! (double) wurzel
std %f2, [%l1] ! x ins o0 und o1 Register schreiben
ld [%l1], %o0 ! fuer den Unterprogrammaufruf
ld [%l1+4], %o1
call quadratwurzel
nop
ld [%o0], %o5
ld [%o1], %o6
set fmt, %l0
mov %l0, %o0 ! fmt
std %f2, [%l1] ! double x nach l1+8
ld [%l1], %o1 ! l1+8 nach o1
ld [%l1+4], %o2 ! l1+12 nach o2
ld [%l6], %o3
ld [%l6+4], %o4
call printf
nop
set 1,%g1
ta 0
Schon mal Danke im voraus
Achja es ist ein "Segmentation Fehler"
Schauen wir uns zuerst mal den Aufrufer an:
main:
set x,%l1 ! Die gewünschte Zahl ins das Register l1 laden
ldd [%l1],%f2 ! x in %f2, %f3
std %f2, [%l1] ! x ins o0 und o1 Register schreiben
ld [%l1], %o0 ! fuer den Unterprogrammaufruf
ld [%l1+4], %o1
call quadratwurzel
nop
Du übergibst in %o0 und %o1 die Zahl, von der Du die Wurzel berechnen möchtest. So weit, so gut. Nun zum Unterprogramm:
quadratwurzel:
save %sp, -96, %sp
ldd [%i0], %f8 ! x ins f8 und f9
Hier interpretierst Du die oberen 32 Bit der übergebenen Zahl (also das Vorzeichenbit, die Charakteristik und einen Teil der Mantisse) als Adresse und versuchst, an dieser Adresse im Speicher 8 Byte zu laden => segfault
So das haeb ich nu gelöst mit:
st %i0, [%fp-8]
st %i1, [%fp-4]
ldd [%fp-8], %f8 ! x ins f8 und f9
Bekomme aber imemrnoch einen Seg Fehler…
Bekomme aber imemrnoch einen Seg Fehler…
Dann nimmst Du halt solange Speicherbefehle raus, bis sie nicht mehr auftreten. Die hier sehen z.B. sehr gefährlich aus:
mov %i0, %l0
ldd [%l0], %f10 ! f10 und f11 fuer XALT
mov %l0, %l2
ldd [%l2], %f12 ! f12 und f13 fuer XNEU
Egal, was ich amche der kack Fehler geht nicht weg.
Wäre echt mal sinnvoll, wenn der Compiler anzeigen würde, WO der Fehler verursacht wird…
Egal, was ich amche der kack Fehler geht nicht weg.
Selbst wenn Du alle Speicherzugriffe entfernst? Das kann nicht sein.
Wäre echt mal sinnvoll, wenn der Compiler anzeigen würde, WO der Fehler verursacht wird…
Der
Compiler soll bei
Laufzeitfehlern was anzeigen? Wie stellst Du Dir das denn bitte vor?
Wäre echt mal sinnvoll, wenn der Compiler anzeigen würde, WO der Fehler verursacht wird…
s/compiler/debugger/
Naja C++ oder Java zeigen das ja auch an. ;)
@ Garou: Wie genau meinst du das? Wie soll/kann ich den Debugger anwenden?
ld [%o1], %o6
Hier dürfte der Fehler liegen (im main-Programm). Du belegst %o6 mit irgendwas, und da das der stack pointer ist, versucht er beim nächsten st oder ld Befehl von diesem aus zu gehen (in printf) und landet natürlich einfach irgendwo, wo er nicht hin darf. Teste einfach mal kurz, was passiert, wenn du die "call printf" Zeile auskommentierst. Du solltest dann keinen Segfault mehr kriegen (natürlich auch keine Ausgabe, einfach gar nichts).
Bei mir war es das, hab ich auch ewig nach gesucht…
Du kannst printf eben nur max. 5 Register übergeben und darfst o6 davor nicht verändern. Schreib doch einfach deine Rechenzahl als Klartext in den String, dann hast du genug Platz für beide doubles. Oder aber du speicherst den einen in einem lokalen Register und rufst dann printf zweimal auf (einmal für die erste Hälfte der Ausgabe, einmal für die zweite).
Noch eine kleine Verständnisfrage meinerseits:
Was genau machen eigentlich die letzten beiden Zeilen in main:
set 1, %g1
ta 0
Ohne sie gehts scheinbar nicht, aber Lehmanns Kommentar dazu ist etwas mager und im Manual finde ich dazu nichts, aus dem ich schlau werde.
Die letzten beiden Zeilen sind einfach dazu da, um ins Betriebssystem zurückzuspringen.
Muss man einfach als "notwendiges Übel" hinnehmen.
Deien Vorschläge werde ich gleich mal ausprobieren.
Du belegst %o6 mit irgendwas, und da das der stack pointer ist
Scharf beobachtet!
Noch eine kleine Verständnisfrage meinerseits:
Was genau machen eigentlich die letzten beiden Zeilen in main:
set 1, %g1
ta 0
Schauen wir einfach mal im Manual nach:
Trap - A vectored transfer of control to supervisor software through a table whose address is given by a privileged IU register (the Trap Base Register (TBR)).
Du kannst also aus dem beschränkten Usermodus heraus spezielle Dienstleistungen des Supervisormodus anfordern. Etwas ausführlicher:
A trap is a vectored transfer of control to the operating system through a special trap table that contains the first 4 instructions of each trap handler. The base address of the table is established by software in an IU state register (the trap base register, TBR). The displacement within the table is encoded in the type number of each trap. Half of the table is reserved for hardware traps, and the other half for software traps generated by trap (Ticc) instructions.
A trap causes the current window pointer (CWP) to advance to the next register window and the hardware to write the program counters into two registers of the new window. The trap handler can access the saved PC and nPC and, in general, can freely use the 6 other local registers in the new window.
A trap may be caused by an instruction-induced exception, or by an external interrupt request not directly related to a particular instruction. Before executing each instruction, the IU checks for pending exceptions and interrupt requests. If any are present, the IU selects the one with the highest priority and causes a corresponding trap to occur.
Eine Übersicht über die vorhandenen Dienstleistungen habe ich auf die schnelle nicht gefunden.
Brauch schnell eien Antwort:
Wie kann ich von einem Rechner am Informatikum mein Programm ausführen?
Übersetzen:
cc deinprogramm.s
Ausführen:
./a.out
Bin utner Linux angemeldet und wenn ich das in der Konsole eingebe, sagt er mir, dass er die ganzen Befehle und Anweisungen nicht kennt.
Bin utner Linux angemeldet und wenn ich das in der Konsole eingebe, sagt er mir, dass er die ganzen Befehle und Anweisungen nicht kennt.
Welche hast Du denn alle ausprobiert?
Hm, Ferndiagnosen sind ja immer schwierig… hast Du es mal mit gcc statt cc versucht?
gcc deinprogramm.s
./a.out
Ansonsten poste doch einfach mal die exakten Fehlermeldungen.
Unter die ganzen meine ich:
temp.s:1: Error: junk at end of line, first unrecognized character is `!'
temp.s:5: Error: junk at end of line, first unrecognized character is `!'
temp.s:17: Error: junk at end of line, first unrecognized character is `!'
temp.s:21: Error: no such instruction: `save %sp,-96,%sp'
temp.s:23: Error: no such instruction: `st %i0,[%fp-8]'
temp.s:24: Error: no such instruction: `st %i1,[%fp-4]'
temp.s:25: Error: no such instruction: `ldd [%fp-8],%f8!x ins f8 und f9'
temp.s:27: Error: no such instruction: `set x4,%l6'
temp.s:28: Error: no such instruction: `ldd [%l6],%f16!2.0 in %f16,%f17'
temp.s:30: Error: bad register name `%i0'
temp.s:31: Error: no such instruction: `bl kleiner'
temp.s:33: Error: bad register name `%i0'
temp.s:34: Error: no such instruction: `be null'
temp.s:37: Error: no such instruction: `fmovs %f9,%f11'
temp.s:38: Error: no such instruction: `fmovs %f8,%f10!XALT=x in f10 udn f11'
temp.s:39: Error: no such instruction: `ldd [%l0],%f10'
temp.s:40: Error: no such instruction: `fdivd %f10,%f16,%f10!XALT=x/2'
temp.s:42: Error: no such instruction: `fmovs %f11,%f13'
temp.s:43: Error: no such instruction: `fmovs %f10,%f12!XNEU=XALT'
temp.s:44: Error: junk at end of line, first unrecognized character is `!'
temp.s:45: Error: no such instruction: `ldd [%l2],%f12!f12 und f13 fuer XNEU'
temp.s:46: Error: no such instruction: `fmovs %f9,%f15'
temp.s:47: Error: no such instruction: `fmovs %f8,%f14!h=x'
temp.s:48: Error: junk at end of line, first unrecognized character is `!'
temp.s:49: Error: invalid character '[' in mnemonic
temp.s:50: Error: no such instruction: `fdivd %f14,%f10,%f14!h=x/XALT'
temp.s:51: Error: no such instruction: `faddd %f12,%f14,%f12!XNEU=(XALT+x/XALT)'
temp.s:52: Error: no such instruction: `fdivd %f12,%f16,%f12!XNEU=(XALT+x/XALT)/2.0'
temp.s:54: Error: bad register name `%l0'
temp.s:55: Error: no such instruction: `be ende'
temp.s:59: Error: no such instruction: `fmovs %f13,%f11'
temp.s:60: Error: no such instruction: `fmovs %f12,%f10!XALT=XNEU'
temp.s:62: Error: no such instruction: `fmovs %f11,%f13'
temp.s:63: Error: no such instruction: `fmovs %f10,%f12!XNEU=XALT'
temp.s:65: Error: no such instruction: `fmovs %f9,%f15'
temp.s:66: Error: no such instruction: `fmovs %f8,%f14!x in Hilfsspeicher'
temp.s:68: Error: no such instruction: `fdivd %f14,%f10,%f14!h=x/XALT'
temp.s:69: Error: no such instruction: `faddd %f12,%f14,%f12!XNEU=(XALT+x/XALT)'
temp.s:70: Error: no such instruction: `fdivd %f12,%f16,%f12!XNEU=(XALT+x/XALT)/2.0'
temp.s:72: Error: bad register name `%l0'
temp.s:73: Error: no such instruction: `bne schleife'
temp.s:77: Error: bad register name `%f12'
temp.s:78: Error: no such instruction: `ld [%l4],%o0'
temp.s:79: Error: no such instruction: `ld [%l4+4],%o1'
temp.s:80: Error: bad register name `%i7+8'
temp.s:81: Error: no such instruction: `restore'
temp.s:83: Error: junk at end of line, first unrecognized character is `!'
temp.s:84: Error: bad register name `%o0'
temp.s:85: Error: bad register name `%i7+8'
temp.s:86: Error: no such instruction: `restore'
temp.s:88: Error: junk at end of line, first unrecognized character is `!'
temp.s:89: Error: bad register name `%o0'
temp.s:90: Error: bad register name `%i7+8'
temp.s:91: Error: no such instruction: `restore'
temp.s:94: Error: no such instruction: `set x,%l1!Die gew�nschte Zahl ins das Register l1 laden'
temp.s:95: Error: no such instruction: `ldd [%l1],%f2!x in %f2,%f3'
temp.s:96: Error: no such instruction: `fsqrtd %f2,%f4!Wurzel mit fsqrtd in %f4,%f5'
temp.s:97: Error: no such instruction: `set x2,%l6'
temp.s:98: Error: bad register name `%f4'
temp.s:100: Error: bad register name `%f2'
temp.s:101: Error: no such instruction: `ld [%l1],%o0!fuer den Unterprogrammaufruf'
temp.s:102: Error: no such instruction: `ld [%l1+4],%o1'
temp.s:107: Error: no such instruction: `ld [%o0],%o5'
temp.s:108: Error: no such instruction: `ld [%o1],%o6'
temp.s:110: Error: no such instruction: `set fmt,%l0'
temp.s:111: Error: bad register name `%l0'
temp.s:113: Error: bad register name `%f2'
temp.s:114: Error: no such instruction: `ld [%l1],%o1!l1+8 nach o1'
temp.s:115: Error: no such instruction: `ld [%l1+4],%o2!l1+12 nach o2'
temp.s:117: Error: no such instruction: `ld [%l6],%o3'
temp.s:118: Error: no such instruction: `ld [%l6+4],%o4'
temp.s:123: Error: no such instruction: `set 1,%g1'
temp.s:124: Error: no such instruction: `ta 0'
Ich hatte eingegeben:
cc aufgabe38.s
Habs auch mit:
gcc aufgabe38.s
probiert kamen aber dieselben Fehlermedungen.
Und Du bist sicher, dass Du an einer Sparc sitzt?
Glaube ich nicht, kA wo die stehen.^^
Ich sitze in D017 und woltle das von heir aus machen.
Glaube ich nicht, kA wo die stehen.^^
In den Arbeitsräumen rechts neben dem Druckerraum, wo der d116_hp sich befindet, stehen definitiv Sparc-Rechner. Du kannst die Sparc-Aufgaben (ohne Umwege) nur auf einer Sparc machen. Wenn Du es unbedingt von einem anderen Rechner aus machen musst, verbinde Dich per SSH mit einer Sparc. Für Windows-Benutzer gibt es sogar einen
eigenen Thread.
Sehr schön mit SSH funktioniert es.^^
Ne Frage:
Der Rückgabewert der Funktion mit double, steht das nun im %f0 und %f1 oder im %o0 und %o1?
Mein Programm funktioniert jetzt mit dem Wert 0.
Bei allen anderen Werten gibt es einen Seg Fehler. -.-
Der Rückgabewert der Funktion mit double, steht das nun im %f0 und %f1 oder im %o0 und %o1?
%f0 und %f1.
So jett zeigt er mir keien Seg Fehler mehr an aber dafür die flaschen Wert der Wurzeln, so ist zum Beispiel Wurzel aus 1 anstatt -1 zeigt er 1000 an und bei 0 zeigt er -1 an.
Hier nochmal der Quelltext. Vielleicht kann mir da ja jemand weiterhelfen.
! Information fuer Binder
.global main
.global printf
! Deklaration von Daten
.section ".data"
.align 8
x: .double 0r-1.0
x2: .double 0r0.0
x3: .double 0r0.0
x4: .double 0r2.0
x5: .double 0r-1.0
fmt:
.ascii "Quadratwurzel von %f\n"
.asciz "mit fsqrtd: %f\n"
fmt2: .asciz "mit Newton-Raphson: %f\n"
! ausfuehrbares Programm
.section ".text"
quadratwurzel:
save %sp, -96, %sp
st %i0, [%fp-8]
st %i1, [%fp-4]
ldd [%fp-8], %f8 ! x in f8 und f9
set x4, %l6
ldd [%l6], %f16 ! 2.0 in %f16, %f17
set x5, %l4
ldd [%l4], %f4 ! -1 in f4 und f5
set x3, %l2
ldd [%l2], %f2 ! 0 in f2 und f3
cmp %i0, %l2 ! Wenn 0 denn 0 zurueckgeben
be null
nop
cmp %i0, %l2 ! Wenn kleiner denn -1 zurueckgeben
bl kleiner
nop
fmovs %f9, %f11 ! XALT in f10 und f11
fmovs %f8, %f10 ! XALT = x in f10 udn f11
fmovs %f11, %f13 ! XNEU in f12 und f13
fmovs %f10, %f12 ! XNEU = XALT
fmovs %f9, %f15 ! h in f14 und f15
fmovs %f8, %f14 ! h = x
fdivd %f14, %f10, %f14 ! h = x / XALT
faddd %f12, %f14, %f12 ! XNEU = (XALT + x/XALT)
fdivd %f12, %f16, %f12 ! XNEU = (XALT + x/XALT) / 2.0
fcmpd %f10, %f12 ! Wenn die gleich sind gehe zum Ende
fbe ende
nop
schleife:
fmovs %f13, %f11
fmovs %f12, %f10 ! XALT = XNEU
fmovs %f11, %f13
fmovs %f10, %f12 ! XNEU = XALT
fmovs %f9, %f15
fmovs %f8, %f14 ! x in Hilfsspeicher
fdivd %f14, %f10, %f14 ! h = x / XALT
faddd %f12, %f14, %f12 ! XNEU = (XALT + x/XALT)
fdivd %f12, %f16, %f12 ! XNEU = (XALT + x/XALT) / 2.0
fcmpd %f10, %f12 ! Wenn die ungleich sind, wiederhole schleife
fbne schleife
nop
ende:
fmovs %f12, %f0
fmovs %f13, %f1
jmp %i7+8
restore
kleiner: ! -1 Wenn x kleiner 0
fmovs %f4, %f0
fmovs %f5, %f1
jmp %i7+8
restore
null: ! 0 wenn x 0 ist
fmovs %f2, %f0
fmovs %f3, %f1
jmp %i7+8
restore
main:
set x,%l1 ! Die gewuenschte Zahl ins das Register l1 laden
ldd [%l1],%f2 ! x in %f2, %f3
fsqrtd %f2, %f4 ! Wurzel mit fsqrtd in %f4, %f5
set x2, %l6
std %f4, [%l6] ! (double) wurzel
set fmt, %l0
mov %l0, %o0 ! fmt
std %f2, [%l1] ! double x nach l1+8
ld [%l1], %o1 ! l1+8 nach o1
ld [%l1+4], %o2 ! l1+12 nach o2
ld [%l6], %o3
ld [%l6+4], %o4
call printf
nop
std %f2, [%l1] ! x ins o0 und o1 Register schreiben
ld [%l1], %o0 ! fuer den Unterprogrammaufruf
ld [%l1+4], %o1
call quadratwurzel
nop
std %f0, [%l2]
ld [%l2], %o1
ld [%l2+4], %o2
set fmt2, %l0 ! Zweite Ausgabe
mov %l0, %o0
call printf
nop
set 1,%g1
ta 0
Hab das Programm gelöst und funktioniert jetzt. = )
Danke für die vielen Hilfen!
Die Kommandozeilenargumente werden an den Leerzeichen getrennt und dann irgendwo im Speicher abgelegt. Dann wird ein Array angelegt, dass die Startadressen dieser Argumente speichert. Die Startadresse dieses Arrays wiederum steht innerhalb von main in %o1 bzw. in %i1 (falls Du in ein save verwendest).
Wie sieht denn ein Array unter Assembler aus?
Ich kann mir das im Moment nur so vorstellen, dass man eine Startadresse erhaelt, ab der dann in jedem Register ein weiterer Wert des Arrays liegt.
Also, falls z.B. %l1 die Startadresse des Arrays waere, wuerde das erste Elemten in %l1, das Zweite in %l1+8, das Dritte in %l1+16 usw. liegen?
Aber mit dem Gedankengang krieg ich irgendwie nicht den richtigen Wert raus, den ich einlese. [26]
Also, wenn ich z.B. "a.out 5" eingebe, wird die "5" irgendwo im Speicher gespeichert.
Dann wird ein Array mit einem Element angelegt, wo die (Start)Adresse von "5" ist.
Und in %o1 steht dann die (Start)Adresse von dem Array.
Also muss ich den Wert in %o1 als Adresse interpretieren, den Wert auf dieser Adresse wieder als Adresse interpretieren, um dann die "5", die auf der Adresse liegt, abzuspeichern?
Nur leider habe ich gerade keine Ahnung, wie ich das umsetzen soll. [9]
Also, falls z.B. %l1 die Startadresse des Arrays waere, wuerde das erste Elemten in %l1, das Zweite in %l1+8, das Dritte in %l1+16 usw. liegen?
Wenn es sich dabei um jeweils 8 Byte große Elemente handelt, ja. (Adressen sind aber z.B. nur 4 Byte groß, und Zeichen nur 1 Byte.)
Also, wenn ich z.B. "a.out 5" eingebe, wird die "5" irgendwo im Speicher gespeichert.
Dann wird ein Array mit einem Element angelegt, wo die (Start)Adresse von "5" ist.
Das Array hat in dem Fall nicht nur einen Eintrag, sondern drei. Der erste Eintrag für "a.out", der zweite Eintrag für "5", und der dritte Eintrag für "" (daran erkennt man, dass keine weiteren Argumente mehr kommen).
Nur leider habe ich gerade keine Ahnung, wie ich das umsetzen soll. [9]
ld [%o1 + 4], %l0 ! %l0 = Adresse des ersten echten Arguments
ldub [%l0] , %l1 ! %l1 = Erstes Zeichen davon
ldub [%l0 + 1], %l2 ! %l2 = Zweites Zeichen davon
ldub [%l0 + 2], %l3 ! %l3 = Drittes Zeichen davon
...
Danke danke!
Es klappt soweit erstmal… denke ich… ausser, dass es mir wahrscheinlich doch zu kompliziert wird…
Ich muss ja anscheinend genau wissen, wie lang meine Zeichenkette ist, um nicht noch irgendwelche willkuerlichen Informationen mit abzugreifen.
Ausserdem gibt er mir den Wert als Ascii-Zeichen raus, wo ich nicht weiss, wie ich das umwandeln soll.
Also, danke erstmal, werd lieber die Hausaufgaben weiter bearbeiten und mich vielleicht ein anderes Mal weiter hiermit beschaeftigen. ^^
Ich muss ja anscheinend genau wissen, wie lang meine Zeichenkette ist, um nicht noch irgendwelche willkuerlichen Informationen mit abzugreifen.
Das letzte Zeichen einer Zeichenkette ist immer die 0. Also vergleiche das geladene Byte einfach mit 0, dann weisst Du, ob Du am Ende bist.
Ausserdem gibt er mir den Wert als Ascii-Zeichen raus, wo ich nicht weiss, wie ich das umwandeln soll.
Klar, Argumente sind nichts weiter als Zeichenketten. Wenn Du vom ASCII-Code einer Ziffer wie '5' auf den Wert 5 kommen willst, ziehe einfach 48 ab (ab 48 fangen die Ziffern 0 bis 9 im ASCII-Code an).