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 + val3

    Erhard 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

    🙂


Anmelden zum Antworten