
Aber ich wühle mich mal durch. Woher kommt das gute Assembler Wissen?

Sehr viel davon: http://www.amazon.de/Assembly-Language- ... 470497025/Architekt hat geschrieben:Woher kommt das gute Assembler Wissen?
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
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
Code: Alles auswählen
movl $4, %eax
movl %eax, (%esp)
Code: Alles auswählen
movl $4, %eax
movl %eax, (%esp)
pop %eax
Code: Alles auswählen
imull 8(%esp), %eax
Code: Alles auswählen
imull 12(%esp), %eax
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
}
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?