mov/add vs lea
-
In einem guten Kommentar steht nie nie nie, was man sehen kann.
argument n kann man aber nicht so einfach erkennen.
-
Erhard Henkes schrieb:
LEA spart sich den Zugriff auf die flags -> weniger µOps.
... und warum nur einmal? warum das zweite mal add?
weil ADD auf den Speicher zugreifen kann (argument 3) - LEA nicht.
-
Erhard Henkes schrieb:
Sind meine Kommentare so ok?
Man bräuchte keine Kommentare, wenn man den Code gleich in AT&T-Syntax ausgeben würde .)
-
weil ADD auf den Speicher zugreifen kann (argument 3) - LEA nicht.
Das Argument sticht nicht, weil der Vorgang gleich ist, man hätte auch schon beim ersten mal add mit speicher machen können anstelle erst nach EDX und anschließend mit LEA addieren.
Wo findet eigentlich das statt? [edx+eax*1] wieso *1 ?
-
Man bräuchte keine Kommentare, wenn man den Code gleich in AT&T-Syntax ausgeben würde .)
Das ist Gewohnheitssache. Die Syntax ist mein geringstes Problem momentan.
-
Erhard Henkes schrieb:
[edx+eax*1] wieso *1 ?
Wahrscheinlich, um zu betonen, dass eax in diesem Fall Index-Register ist. Das muss (sollte) man ja bei der Intel-Syntax wahrscheinlich explizit machen...
-
[edx+eax*1] wieso *1 ?
Nennt sich Skalierung bzw. Skalierungsfaktor. Davon gibt es *1, *2, *4, *8. (Ein Displacement passt auch noch rein.)
Damit wird das jeweilige Indexregister multipliziert. Sinnvoll bei Feldzugriffen. Finde gerade keinen Link dazu.
"[edx + eax*4 - 8]" vs. "-8(%edx, %eax, 4)"
Soweit zur Syntax.
-
merker schrieb:
... Soweit zur Syntax.
Das ist richtig, aber wie würde man in der Intel kompatiblen Syntax folgende Befehle eingeben:
movl $42, (%eax) movl $42, (, %eax)
eax-Register einmal als Basisregister und einmal als Indexregister
-
mov [eax], 42 ; C6 00 2A mov [eax*1], 42 ; C6 00 2A
Aber korrekterweise müsste Skalierung *1 bei einem Index- ohne Basisregister via SIB zusammengebaut werden:
mov [eax*1], 42 ; C6 04 05 00 00 00 00 2A mov [eax*1+000000000h], 42 ; C6 04 05 00 00 00 00 2A
-
Hast du dazu einen Assembler benutzt oder manuell assembliert
Nach den Kommentaren in diesem Code zu urteilenmerker schrieb:
mov [eax], 42 ; C6 00 2A mov [eax*1], 42 ; C6 00 2A
stimmt was nicht... beide Befehle erzeugen gleichen Code C6 00 2A...
Der zweite Codeausschnitt scheint richtig zu sein. Ich hab es mit dem GNU as überprüft
Aus.section .text myfunc: movl $42, (%eax) movl $42, (, %eax) ret
wird
00000000 <myfunc>: 0: c7 00 2a 00 00 00 movl $0x2a,(%eax) 6: c7 04 05 00 00 00 00 movl $0x2a,0x0(,%eax,1) d: 2a 00 00 00 11: c3 ret
Übrigens wollte ich die Konstante 42 als 32-bit Konstante. Als 8-Bit Konstante (wie in deinem Beispiel):
.section .text myfunc: movb $42, (%eax) movb $42, (, %eax) ret
disassembliert:
00000000 <myfunc>: 0: c6 00 2a movb $0x2a,(%eax) 3: c6 04 05 00 00 00 00 movb $0x2a,0x0(,%eax,1) a: 2a b: c3 ret
-
Mein (Intel-Syntax-)Assembler hält ein Indexregister mit Skalierung *1 ohne Basisregister für sinnfrei. Darum der gleiche Code im ersten Beispiel.
Es aber via Syntax trotzdem zu erzwingen, könnte auch sinnfrei sein.
-
Deswegen sage ich, die AT&T Syntax ist am besten durchdacht, siehe hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-275053-and-start-is-40.html
-
movb $0x2a,(%eax) ; c6 00 2a movb $0x2a,0x0(,%eax,1) ; c6 04 05 00 00 00 00 2a
Wußte hier der Assembler nicht, daß beide Befehle die gleiche Wirkung haben?
Oder wurde das durch die Syntax erzwungen?
-
Das wurde durch die Syntax erzwungen. Ich bin der Meinung, auch wenn beide Befehle gleiche Wirkung haben, darf der verwendete Assembler diesbezüglich keine Entscheidungen treffen. Der Programmierer entscheidet sich für die eine oder andere Variante und der Assembler muss diese "gehorsam" akzeptieren und entsprechend übersetzen. Wenn der Assembler trotzdem solche Entscheidungen trifft, dann ist das eine nicht zu vernachlässigende Limitierung. Das würde ja bedeuten, der Programmierer denkt, er habe mit dem Assembler volle Kontrolle usw., nutzt aber nur eine Teilmenge von dem, was die CPU wirklich kann...
-
Ein klares Statement von Dir. Woraus aber folgt, daß sich ein ATT-Syntax-Assembler niemals weiterentwickeln kann (oder soll). Neue Befehle aufnehmen, das wars dann schon.
-
Ja, der GNU Assembler hat nur eine rudimentäre Unterstützung für Makros, hat ein Paar bekannte Bugs hinsichtlich FPU Operationen, die wahrscheinlich niemals "gefixt" werden wegen der Abhängigkeit zu älteren Compilern und wenn ich es als Laie beurteilen kann, die Weiterentwicklung kann nur mit der Aufnahme von neuen Befehlen stattfinden.
Aber was wären die "Features" von anderen Assemblern, bei denen man sagen würde, sie wären "weiterentwickelter"...?