Assembler: Fehlerhafter Stackframe
Re: Assembler: Fehlerhafter Stackframe
Naja, bin nicht so vertraut mit Assembler, also hauen mich diese ganzen Informationen natürlich erstmal um.
Aber ich wühle mich mal durch. Woher kommt das gute Assembler Wissen?
Aber ich wühle mich mal durch. Woher kommt das gute Assembler Wissen?
Re: Assembler: Fehlerhafter Stackframe
Sehr viel davon: http://www.amazon.de/Assembly-Language- ... 470497025/Architekt hat geschrieben:Woher kommt das gute Assembler Wissen?
Ein bisschen von dem: http://www.amazon.de/Hacking-Art-Exploi ... 593271441/
Und vor allem wochenlanges Durchsteppen von fremden, disassemblierten C-Code: https://www.hacking-lab.com/ Wenn du mal disassemblierte Netzwerk-Services mit Forks und aktiviertem ASLR exploitest, ist der Assembler-Code schon Nebensache, man sieht nur mehr Hex-Adressen und weiß worum es geht
Re: Assembler: Fehlerhafter Stackframe
Ich werde mir wohl auch demnächst am besten ein entsprechendes Buch zulegen.
Aber ich hoffe, bis dahin darf ich dich noch etwas "nerven".
Habe auch direkt eine Frage. Von dem folgenden Programm hatte ich die Ausgabe 12 und 32 erwartet. Ich bekomme aber 12 und 48:
Ich kann es mir nur damit erklären, dass der Wert 16 irgendwo im Register noch steht und sich irgendwie auf 32 rauf addiert. Irgendwie komme ich noch nicht ganz hinter die Materie.
Und ja mein Assembler ist in der Regle nicht gut optimiert. Es wird auto-generiert durch meinen "Compiler" und daher muss ich auf einige Optimierungen verzichten, wenn ich noch durchsteigen will.
Aber ich hoffe, bis dahin darf ich dich noch etwas "nerven".
Habe auch direkt eine Frage. Von dem folgenden Programm hatte ich die Ausgabe 12 und 32 erwartet. Ich bekomme aber 12 und 48:
Code: Alles auswählen
.text
.globl _prog
_prog:
push %ebp
movl %esp, %ebp
subl $16, %esp
movl $4, %eax
movl %eax, (%esp)
movl $8, %eax
movl %eax, 4(%esp)
movl (%esp), %eax
push %eax
movl 4(%esp), %eax
addl 8(%esp), %eax
addl $4, %esp
movl %eax, 8(%esp)
movl 8(%esp), %eax
push %eax
call _println_int
addl $4, %esp
# Hier muss wohl irgendwas gecleart/gepopt werden?!
movl (%esp), %eax
push %eax
movl 4(%esp), %eax
imull 12(%esp), %eax
addl $4, %esp
movl %eax, 12(%esp)
movl 12(%esp), %eax
push %eax
call _println_int
addl $4, %esp
addl $16, %esp
pop %ebp
ret
.data
Und ja mein Assembler ist in der Regle nicht gut optimiert. Es wird auto-generiert durch meinen "Compiler" und daher muss ich auf einige Optimierungen verzichten, wenn ich noch durchsteigen will.
Re: Assembler: Fehlerhafter Stackframe
Ersteres aus meinem vorigen Beitrag kann ich dir sehr ans Herz legen.Architekt hat geschrieben:Ich werde mir wohl auch demnächst am besten ein entsprechendes Buch zulegen.
Ich hab dir mal alle paar Instruktionen den Stack aufgezeichnet, damit sollte das nachvollziehbar sein:Architekt hat geschrieben:Ich kann es mir nur damit erklären, dass der Wert 16 irgendwo im Register noch steht und sich irgendwie auf 32 rauf addiert. Irgendwie komme ich noch nicht ganz hinter die Materie.
Code: Alles auswählen
.text
.globl _prog
_prog:
push %ebp
movl %esp, %ebp
subl $16, %esp
movl $4, %eax
movl %eax, (%esp)
# +-----+
# 0 | 4 |
# 4 | |
# 8 | |
# 12 | |
# 16 | |
# +-----+
# eax: 4
movl $8, %eax
movl %eax, 4(%esp)
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | |
# 12 | |
# 16 | |
# +-----+
# eax: 8
movl (%esp), %eax
push %eax
# +-----+
# 0 | 4 |
# 4 | 4 |
# 8 | 8 |
# 12 | |
# 16 | |
# +-----+
# eax: 4
movl 4(%esp), %eax
addl 8(%esp), %eax
# +-----+
# 0 | 4 |
# 4 | 4 |
# 8 | 8 |
# 12 | |
# 16 | |
# +-----+
# eax: 12
addl $4, %esp
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | |
# 12 | |
# 16 | |
# +-----+
# eax: 12
movl %eax, 8(%esp)
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | |
# 16 | |
# +-----+
# eax: 12
movl 8(%esp), %eax
push %eax
# +-----+
# 0 | 12 |
# 4 | 4 |
# 8 | 8 |
# 12 | 12 |
# 16 | |
# +-----+
# eax: 12
call _println_int # 12 wird ausgegeben
addl $4, %esp
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | |
# 16 | |
# +-----+
# eax: ?
movl (%esp), %eax
push %eax
# +-----+
# 0 | 4 |
# 4 | 4 |
# 8 | 8 |
# 12 | 12 |
# 16 | |
# +-----+
# eax: 4
movl 4(%esp), %eax
# +-----+
# 0 | 4 |
# 4 | 4 |
# 8 | 8 |
# 12 | 12 |
# 16 | |
# +-----+
# eax: 4
imull 12(%esp), %eax
# +-----+
# 0 | 4 |
# 4 | 4 |
# 8 | 8 |
# 12 | 12 |
# 16 | |
# +-----+
# eax: 48
addl $4, %esp
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | |
# 16 | |
# +-----+
# eax: 48
movl %eax, 12(%esp)
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | 48 |
# 16 | |
# +-----+
# eax: 48
movl 12(%esp), %eax
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | 48 |
# 16 | |
# +-----+
# eax: 48
push %eax
# +-----+
# 0 | 48 |
# 4 | 4 |
# 8 | 8 |
# 12 | 12 |
# 16 | 48 |
# +-----+
# eax: 48
call _println_int # 48 Wird ausgegeben
addl $4, %esp
# +-----+
# 0 | 4 |
# 4 | 8 |
# 8 | 12 |
# 12 | 48 |
# 16 | |
# +-----+
# eax: ?
addl $16, %esp
pop %ebp
ret
Re: Assembler: Fehlerhafter Stackframe
Nicht ganz. Ich sehe mich bestätigt, dass ich den Stack vollgemüllt habe. Aber leider habe ich keine Ahnung, wie ich das gerade biegen könnte.
Ich muss ja, meiner Meinung nach, den Stack clearen. Aber wie mache ich das?
Eine Änderung von
zu
führt zu einem Fehler. Ich liege doch damit richtig, dass ich den Stack "sauber" halten muss, oder? Oder missverstehe ich das?
edit:
Achso, es müsste heißen, nicht Zumindest funktioniert das. Ich hoffe das ist korrekt.
Ich dachte imull speichert es in dem ersten Register.
edit2:
Also während ich bei add und sub stets mit dem höchsten Offset arbeiten kann (also in dem Beispiel 12 -> 12(%esp)) muss ich bei imull darauf achten, mit dem vorherigen, also 8(%esp) zu arbeiten. Kann man das so sagen?
In meiner Assembler Klasse würde dann das ganze folgendermaßen aussehen:
Die globalen Operationen add, sub, pop und mul leiten einfach die Assembler Entsprechung mit dem jeweiligen Registern in ein std::ostream.
_stackSize wiederum ist der höchste Wert/Offset. Jedesmal wenn wir eine Variable speichern, steigt er um 4, damit wir am Ende vor dem eigentlichen Programm den Speicher mit subl $_stacksize anfordern können (und hinterher natürlich genauso wieder freigeben).
Ich muss ja, meiner Meinung nach, den Stack clearen. Aber wie mache ich das?
Eine Änderung von
Code: Alles auswählen
movl $4, %eax
movl %eax, (%esp)
Code: Alles auswählen
movl $4, %eax
movl %eax, (%esp)
pop %eax
edit:
Achso, es müsste
Code: Alles auswählen
imull 8(%esp), %eax
Code: Alles auswählen
imull 12(%esp), %eax
Ich dachte imull speichert es in dem ersten Register.
edit2:
Also während ich bei add und sub stets mit dem höchsten Offset arbeiten kann (also in dem Beispiel 12 -> 12(%esp)) muss ich bei imull darauf achten, mit dem vorherigen, also 8(%esp) zu arbeiten. Kann man das so sagen?
In meiner Assembler Klasse würde dann das ganze folgendermaßen aussehen:
Code: Alles auswählen
void add() {
::add(_buf, ESP, EAX, _stackSize);
::add(_buf, 4, ESP); // restore Stack Pointer - pop ginge auch
}
void sub() {
::sub(_buf, EAX, ESP, _stackSize);
::pop(_buf, EAX);
}
void mul() {
::mul(_buf, ESP, EAX, _stackSize - 4); // -4 statt wie oben einfach _stackSize
::add(_buf, 4, ESP); // restore Stack Pointer - pop ginge auch
}
_stackSize wiederum ist der höchste Wert/Offset. Jedesmal wenn wir eine Variable speichern, steigt er um 4, damit wir am Ende vor dem eigentlichen Programm den Speicher mit subl $_stacksize anfordern können (und hinterher natürlich genauso wieder freigeben).
Re: Assembler: Fehlerhafter Stackframe
Ok, edit2 war ein Trugschluss. Verdammt. :/ Es klappt nur in dem Anwendungsfall. In anderen führt es dennoch zu Fehlern.
Re: Assembler: Fehlerhafter Stackframe
Damit nimmst du recht umständlich 2 Werte vom Stack. Willst du das?Architekt hat geschrieben:Eine Änderung vonzuCode: Alles auswählen
movl $4, %eax movl %eax, (%esp)
führt zu einem Fehler.Code: Alles auswählen
movl $4, %eax movl %eax, (%esp) pop %eax
Du musst nicht. Ich würde dir raten genau so viel Platz am Stack zu verwenden damit du sauber programmieren kannst. Nicht mehr aber auch nicht weniger.Architekt hat geschrieben:Ich liege doch damit richtig, dass ich den Stack "sauber" halten muss, oder? Oder missverstehe ich das?
Dann multiplizierst du 4 * 8, was dein gewünschtes Ergebnis wäre. Allerdings weiß ich ja nichtmal was du versuchst zu programmieren bzw. welchen Code du da gerade in Assembler übersetzt.Architekt hat geschrieben:Achso, es müssteheißen, nichtCode: Alles auswählen
imull 8(%esp), %eax
Zumindest funktioniert das. Ich hoffe das ist korrekt.Code: Alles auswählen
imull 12(%esp), %eax
Ich bezweifle stark, dass du das mit deiner jetzigen Übersetzung allgemein so sagen kannst. Eine zeilenweise Konvertierung nach Assembler wird dir wohl auch nicht gelingen, du musst dir im C++-Code zumindest einige Ergebnis-Offsets speichern, um später noch darauf zurückgreifen zu können.Architekt hat geschrieben:Also während ich bei add und sub stets mit dem höchsten Offset arbeiten kann (also in dem Beispiel 12 -> 12(%esp)) muss ich bei imull darauf achten, mit dem vorherigen, also 8(%esp) zu arbeiten. Kann man das so sagen?
Re: Assembler: Fehlerhafter Stackframe
Hm, ungut.
Ich kann dir das ganze gerne mal als zip packen und hier hochladen, allerdings sind 300 Zeilen Compiler und 200 Zeilen Assembler Klassen Code. :/ Keine Ahnung, ob du das möchtest. ^^
Ich muss mal sehen, wie ich das am besten mache. :/
Ich kann dir das ganze gerne mal als zip packen und hier hochladen, allerdings sind 300 Zeilen Compiler und 200 Zeilen Assembler Klassen Code. :/ Keine Ahnung, ob du das möchtest. ^^
Ich muss mal sehen, wie ich das am besten mache. :/
Re: Assembler: Fehlerhafter Stackframe
Ich hätte vorgeschlagen du implementierst dir eine High-Level-Speicherverwaltung und wenns wo Probleme gibt versuche ich zu helfen.
Re: Assembler: Fehlerhafter Stackframe
Klingt komplex. Es muss doch auch so gehen.
edit:
In dem Tutorial, auf das ich mich stütze, macht er das so, dass er für Variablen negative Offsets benutzt:
http://magazin.c-plusplus.de/artikel/Compilerbau
Speziell hier in seinem VarManager: http://www.c-plusplus.de/magazin/bilder ... r_man1.cpp
Ist das die Rätsels Lösung?
edit:
In dem Tutorial, auf das ich mich stütze, macht er das so, dass er für Variablen negative Offsets benutzt:
http://magazin.c-plusplus.de/artikel/Compilerbau
Speziell hier in seinem VarManager: http://www.c-plusplus.de/magazin/bilder ... r_man1.cpp
Ist das die Rätsels Lösung?