Assemblercode sum der Zahlen 1 bis 10 in VM ausgeben?
Ich nutze hier wieder mov eax, 4 sowie mov ebx, 1
dann berechne ich die Summe der Zahlen von 1 bis 10 = 55
Nun möchte ich dieses Ergebnis am Ende auf der Konsole ausgeben:
Mit mov eax, 1 sowie mov ebx, 0 int 80h
beende ich den Code
Warum wird jetzt das Ergebnis nicht auf der Konsole der VM ausgegeben?
Schreiben Sie ein Assemblerprogramm, das die Zahlen von 1 bis 10 addiert und das Ergebnis als Exit-Wert ausgibt.
2 Antworten
write dient dazu eine Folge von Bytes in eine Datei zu schreiben, wenn Du an STDOUT schreibst und das die Konsole ist, dann muß das natürlich auch etwas sein, womit die Konsole etwas anfangen kann.
Wenn Du also den numerischen Wert 10 ausgeben wolltest, dann müßtest Du an write die Zeichenkodierung von 1 und 0 übergeben, bei ASCII also 0x31 0x30.
Davon ab sehe ich nichtmal, wo Du hier die Adresse der Bytefolge oder die Anzahl übergibst.
Ich habe mir gedacht ich schreiben den Code so wie von mir angegeben.
Ich habe die Summe der Zahlen von 1 bis 10 im register edi berechnet. Wie gebe ich jetzt das Register edi als Exit-Wert aus?
Wie schonmal geschrieben bin ich Anfänger in Assembler Programmierung.
Ich habe doch hier die Summe der Zahlen von 1 bis 10 richtig berechnet 55. Wie gebe ich die jetzt aus?
Indem Du diesen "Int" in eine Bytefolge konvertierst, die der Texkodierung der 55 entspricht.
Vorschalg, nimm eine andere Sprache und Schreibe eine Funktion, die einen Int erhält und daraus eine ASCII-kodierte Bytefolge der Ziffern der Dezimaldarstellugn erzeugt.
Also genau die Umkehrund von String to Integer.
Danach kannst Du Dir dann überlegen, wie Du das in ASM umsetzen kannst.
char c = 55;
String to Integer
Integer.valueOf("55");
Ich hab ehrlich gesagt keine Ahnung, wie ich das in Assembler umsetzen soll
char *i2a(unsigned int v){
static char buffer[32];
buffer[31]=0;
int i=30;
for (;v>0 && i>=0;--i){
buffer[i]=(v%10)+'0';
v/=10;
}
return &buffer[i+1];
}
So könnte man eien Konversion machen.
oder so:
: (u.) ( u -- ) base @ u/mod ?dup if recurse then .digit emit ;
: u. ( u .. ) (u.) space ;
Eine Version der genannten rekursiven Variante ohne Puffer. Rein in die Rekursion mit stapeln der ASCIIs auf dem Stack, raus aus der Rekursion mit Ausgabe dieser.
Passt.
Okay, wie wäre es damit, anstatt des Puffers pushe ich auf den Stack, da dieser grow down ist. Dadurch erhalte ich automatisch die Umkehrung der Ziffernfolge und kann das trotzdem iterativ machen?
Letztlich nutze ich den den buffer in C als grow down stack.
Ich erspare mir damit das Umschichten von Resultaten vom Stack in den Puffer, weil ich die Resultate gleich da belassen kann, wo sie zurückgegeben wurden, auf dem Stack.
Ich hol ja auch nicht meine Socken aus der Schublade, steck sie in den Kühlschrank, und hol sie dann von dort zum Zweck des Anziehens gleich wieder wieder heraus.
Eine Zahl, dargestellt als binärer Wert, ist kein Text, den man ausgeben kann. Ein Text besteht aus einer Folge von Zeichen, eine binärer Wert nicht.
OK. D .h ich brauche in dem Fall das
mov eax, 4
mov ebx, 1
nach main: gar nicht?
Du wirst eine binäre Zahl in eine Folge von Zeichen umsetzen wollen.
Wenn dir Rekursion bereits ein Begriff ist - das lässt sich verwenden um einen Puffer für die Zeichen überflüssig zu machen.
Denn bedenke, das zuletzt konvertierte Zeichen ist jenes, welches du zuerst ausgeben möchtest.
Bitte meine Fragen beantworten: Brauche in meinem Code jetzt das
main:
mov eax, 4
mov ebx, 1
oder nicht?
Ja, das braucht du, wenn du eine Folge von Zeichen ausgeben möchtest.
Ok. Danke! Jetzt will ich ja keine Folge von Zeichen ausgeben sondern eine Zahl die 55, dich ich im Register edi gespeichert/errechnet habe. Wie gebe ich dieses edi jetzt auf der Konsole aus?
Des Ergebnis soll als Exit-Wert ausgegeben werden
Indem du einen Text ausgibst, der aus zwei Zeichen besteht, wovon jedes dieser beiden Zeichen als "5" darstellt wird. Bei diesen Zeichen handelt es sich um ASCII 53.
Ich will doch das Ergebnis ausgeben, was in dem Register edi steht.
Bitte Code, ich hab keine Ahnung was ich machen muss.
Die Ausgabe möchte eine Zeichenfolge. Du hast das Ergebnis als binären Wert. Den willst du in eine Zeichenfolge konvertierten.
Rekursiv geht das (nach beliebiger Zahlenbasis) in 11 Instruktionen. Vielleicht sogar weniger, aber 11 ist meine bisher beste Lösung.
Nur nach dezimaler Darstellung ist klein bissel einfacher.
Als Zahl im Binärsystem, also bestehend aus Nullen und Einsen, ist noch einfacher.
Des Ergebnis soll als Exit-Wert ausgegeben werden
Darum dass ich frage, denn in assembly bestimmt er seine eigenen Konventionen, ohne sich an die von welcher auch immer Hochsprache halten zu müssen. Möchte er den in einem designierten Register übergeben? Auf dem Stack? Auf einem zweiten, für Daten dedizierten, Stack? In einer "subroutine result structure" zu der er einen pointer retourniert?
Weiterhin scheint er zwischen "Ausgeben" und "Zurückgeben/Retournieren" nicht zu unterscheiden, weswegen ich dazu ebenfalls mehr Klarheit benötige.
Ob ihm der Unterschied zwischen Wert einer Zahl und Darstellung einer Zahl ein Begriff ist, ist auch noch nicht deutlich.
Wert der Zahl 55. Darstellung der Zahl in Maschinencode: 110111
In meinem Code habe ich in dem Register esi die Summe der Zahlen von 1 bis 10 berechnet. Dies ist 55. Das Ergebnis soll als Exit-Wert ausgegeben werden.
"Über das Register ebx kann ein Exit-Code zwischen 0 und 255 definiert werden."
mov ebx 0
Dann gibst du das Ergebnis in ebx zurück, und schreibst dann eine Routine, die es als eine Folge von Nullen und Einsen ausgibt.
ASCII vom Zeichen, das eine 0 anzeigt, ist 48, das Zeichen, das wie ein Eins aussieht, hat ASCII 49.
Bloss weil eine Zahl als Folge von Nullen und Einsen dargestellt wird, macht das daraus aber keinen "Maschinencode"
Danke für deine Mühen, aber deine Erklärungen sind mir teilweise nicht verständlich. Wie gesagt bin ich Anfänger in Assemble. Die Aufgabe die ich bearbeiten soll, habe ich oben bei KarlRanseierIII Antworten eingefügt.
MFG
Da steht aber nichts mehr von "auf Konsole ausgeben" dabei. Das war aber was du in deiner Frage wissen wolltest, warum nichts auf Konsole ausgegeben wird.
Fragen zu stellen, die zum eigentlichen Problem keinen Bezug haben, hat aber nichts mit fehlender Kenntnis von Assembly zu tun.
Da geb ich dir recht.
"Schreiben Sie ein Assemblerprogramm, das die Zahlen von 1 bis 10 addiert und das Ergebnis als Exit-Wert ausgibt."
=> Was ist damit gemeint, das Ergebnis als Exit-Wert ausgeben?
Ein Exit-wert ist ein Wert, der auf definiertem Weg zurückgegeben wird nach Aufruf und Abarbeitung, üblicherweise von einem Programm am Ende der Ausführung zurück an ein aufrufendes Betriebssystem.
Das wird z.B. dafür verwendet, dass ein Programm dem Betriebssystem mitteilen kann, ob es ohne Fehler das Programmende erreichte, oder, falls nicht, um welche Art Fehler (anhand einer Zahl) es sich handelt.
Ok, nochmal zurück zu meinem Programm mit meiner Aufgabe.
Ich habe die Zahlen von 1 bis 10 über die register, esi und edi addiert.
So jetzt steht am Ende meines Programms im Register edi als "Ergebnis" der Wert 55.
"Schreiben Sie ein Assemblerprogramm, das die Zahlen von 1 bis 10 addiert und das Ergebnis als Exit-Wert ausgibt."
=> Wie gebe ich jetzt das Ergebnis als Exit-Wert aus?
=> Was soll man hier tun?
Danke für deine Mühen. Wie gesagt bin ich Anfänger in Assemble und deine Erklärungen sind mir teilweise nicht verständlich.
Die Aufgabe wo ich bearbeiten soll ist einfach:
"Schreiben Sie ein Assemblerprogramm, das die Zahlen von 1 bis 10 addiert und das Ergebnis als Exit-Wert ausgibt.
In das Register ebx kann ein Exit-Code zwischen 0 und 255 abgelegt werden. Der Exit-Code des zuletzt aufgerufenen
Programms kann unter Linux mit der Anweisung echo $? abgefragt werden.
Diese Assemblerbefehle können bei der Lösung der Aufgaben hilfreich sein:
• inc/dec
– Inkrementieren und Dekrementieren des Wertes (Inhalts) eines Registers/einer Speicherzelle
• add/sub
– Addieren/Subtrahieren des Inhalts eines Registers/Speicherzelle mit/von einem Register oder Speicherzelle oder
einer Konstanten
– Beachte: Zwei Speicheradressen als Operanden sind nicht zulässig (1 1
2 -Adressmaschine)
• cmp
– Vergleich eines Registers oder Speicherzelle mit einem Register oder Speicherzelle oder einer Konstanten
– Das Ergebnis des Vergleiches kann für einen bedingten Sprung benutzt werden. Zu bevorzugen ist jedoch die
Verwendung von Flags, die ohnehin nach jeder Operation gesetzt werden. Beispiele s.u.
• jnz / jz / je / jne
– Bedingte Sprünge jump not-zero, jump zero, jump equal, jump not-equal"