Frage zu Assembler und der Syntax
-
Die Funktion ist ja bereits vom Compiler kommentiert
Kommentare beginnen mit dem #-Zeichen:
.text .p2align 2,,3 .globl _doSomething .def _doSomething; .scl 2; .type 32; .endef _doSomething: /APP # 4 "C:\temp\step1\main.c" 1 nop # 0 "" 2 # 6 "C:\temp\step1\main.c" 1 nop # 0 "" 2 /NO_APP movl 4(%esp), %eax # val1, val1 addl 8(%esp), %eax # val2, tmp63 addl 12(%esp), %eax # val3, tmp62 ret
Ausschnitt der Stelle, wo die Argumente aufaddiert werden:
movl 4(%esp), %eax # val1, val1 addl 8(%esp), %eax # val2, tmp63 addl 12(%esp), %eax # val3, tmp62
movl steht für "move long", long ist 32-Bit
addl steht für "add long"
val1, val2 und val3 (in den Kommentaren) stammen direkt aus der main.c:int doSomething(int val1, int val2, int val3)
tmp63 und tmp62 sind Zwischenergebnisse, vom Compiler automatisch generiert:
tmp63 = val1 + val2
tmp62 = tmp63 + val3Erhard Henkes schrieb:
Ehrlich gesagt finde ich beides, sowohl Intel als auch AT&T Syntax, nicht eindeutig und eingängig genug. Daher bleibe ich einfach zwischen beiden unentschieden und versuche beides zu verstehen und zu nutzen.
Ich denke, die Überzeugung und Zuneigung zur AT&T Syntax und GNU Assembler kommt noch
Ich denke, wenn man einen Assembler als Funktion betrachtet, die eingegebene Befehle in die Maschinenbefehle übersetzt/transformiert/abbildet/was auch immer, dann gilt folgendes:
GNU Assembler ist bijektiv
Rest ist surjektiv, hm, tja, bleibt nichts anderes übrig:
-
doSomething wird gar nicht aufgerufen
Meine Frage war: wie wird denn addiert, wenn doSomething bei dir nirgends aufgerufen wird? Da stimmt doch was nicht.
-
Es wurde wegoptimiert, weil das Ergebnis der Funktion niergends im Programm verwendet wird... ausser der NOPs, weil man diese mit asm("") eingefügt hat und Code in asm("") wird vom Compiler ohne weiteres übernommen, weil es wird optimistisch davon ausgegangen, dass der Programmierer weiss, was er da mit asm("") macht
-
abc.w schrieb:
...
Ausschnitt der Stelle, wo die Argumente aufaddiert werden:movl 4(%esp), %eax # val1, val1 addl 8(%esp), %eax # val2, tmp63 addl 12(%esp), %eax # val3, tmp62
movl steht für "move long", long ist 32-Bit
addl steht für "add long"
...Mir kommt das Grausen, die Syntax (links Displacement und Quelle, rechts Ziel) brrr...
Ich bleib bei der Intel-Syntax: mov Ziel, Quelle
mov eax, [esp+4] ; eax ist 32-Bit also braucht man nicht ; mov eax, dword ptr [esp+4] schreiben. add eax, [esp+8] add eax, [esp+12]
-
Birne schrieb:
Mir kommt das Grausen, die Syntax (links Displacement und Quelle, rechts Ziel) brrr...
Ich frage mich, warum
Man lernt seit dem ersten Schuljahr, von links nach rechts zu lesen und plötzlich kommt einem das Grausen, weil es richtig da steht und man doch von recht nach links lesen möchte
-
Die Reihenfolge opcode source, destination ist sicher intuitiver als der umgekehrte Weg. Das spricht für AT&T. Mich stören die unverständlichen % bzw. %% und auch so etwas: 4(%esp)
Wir können es aber nicht ändern, also sollten wir uns an beides gewöhnen. NASM verwendet standardisiert Intel syntax, und GCC liebt AT&T. Also bleibt nur volle Akzeptanz beider Methoden.
-
Mit dem %-Zeichen wollte man wahrscheinlich zwischen den Registern und Variablen unterscheiden. Man kann z.B. eine Variable eax anlegen und das Register %eax in der Variable eax speichern:
.section .bss eax: .int 0 # Variable eax .section .text movl %eax, eax # Register %eax speichern in der Variable eax
Sprich, Register sind was besonderes und verdienen das %-Zeichen
Die Kombination %% muss man nur im Inline-Assembler von gcc verwenden, warum auch immer. Weiss es jemand, warum?
Vielleicht, weil die Inline-Assembler Strings so was wie printf Formatstrings sind... Bei printf muss man ja auch %d, %u, %X usw. verwenden und speziell bei % muss man %% eingeben:printf("abc.w hat 100%% Recht!\n");
-
abc.w schrieb:
Man lernt seit dem ersten Schuljahr, von links nach rechts zu lesen ...
Genau!
eax = 5 -> mov eax, 5 ebp = esp -> mov ebp, esp eax = eax - ebx -> sub eax, ebx eax = ebx * 1234 -> imul eax, ebx, 1234
-
@merker: das hat auch was
Also wie gesagt, schluss mit dem nutzlosen intel vs. at&t.
-
Möchte nur zum Schluss eine Anmerkung machen, dass es diese Art der Syntax (mit Zuweisungen usw.) in der Praxis wirklich gibt. Bei Blackfin DSPs. Siehe z.B. hier: http://docs.blackfin.uclinux.org/doku.php?id=simple_hello_world_application_example_asm