lea und Dekrement/Inkrement



  • In dem Code wird zuerst 8 nach edi geschoben und nach der zweiten Zeile enthält edi den Wert 7. Warum funktioniert in dem folgenden Code lea wie ein dekrement?

    Zuerst scheibe ich den Fixwert nach edi. Danach lade ich doch aber die Adresse von edi+(-1) nach edi. Wieso funktioniert das und warum wird nicht einfach dec verwendet?

    movl  $8, %edi 
    leal  -1(%edi), %edi
    

    Danke!


  • Mod

    lea wertet einen speicheroperanden aus, anstatt allerdings auf den speicher zuzugreifen, wird die benutzte adresse dem ziel zugewiesen. das kann vorteilhaft sein, weil der speicherbezug jeden beliebigen modus verwenden kann - auf diese weise lassen sich bestimmte kompliziertere berechnungen durch einen befehl ausdrücken: im 32bit-modus besteht so ein adressbezug aus:
    reg1 + reg2 * scale + offset
    dabei sind reg1 und reg2 zwei beliebige register (oder auch ein und dasselbe), scale eine konstante (1,2,4 oder 😎 und offset eine beliebige konstante. sofern also ein arithmetischer ausdruck in dieser form darstellbar ist, hat man die möglichkeit, das ergebnis unmittelbar in einem befehl zu berechnen. es gibt dabei zwei dinge zu beachten:
    - lea beeinflusst keine flags
    - zumindest auf intel prozessoren ist es im regelfall deutlich langsamer als ein entsprechendes add,sub etc. sofern der ausdruck so einfach ist, dass er durch diese befehle zu berechnen wäre.
    interessante anwendungen sind z.b. die schnelle multiplikation mit 3,5 und 9 (für 2,4,8 würde man shl benutzen):

    lea  (%eax,%eax,2),%eax
    lea  (%eax,%eax,4),%eax
    lea  (%eax,%eax,8),%eax
    

    warum in deinem fall kein dec verwendet wurde ist ohne den knotext nicht zu beantworten. zumal das ergebnis ja ohnehin feststeht, und man gleich 7 in edi speichern könnte.



  • Hallo und danke!

    Ich bin darauf gestossen, als ich mir den asm Code angeschaut hab, den der GCC bei verschiedenen Optimierungen erzeugt. Folgende C Funktion erzeugt den asm Code:

    int dec(int x)
    {
      return --x;
    }
    
    /*Kompiliert für AMD64 mit -O3*/
    dec:
    .LFB26:
            leal    -1(%rdi), %eax
            ret
    
    /*Ohne -O3*/
    dec:
    .LFB5:
            pushq   %rbp
    .LCFI0:
            movq    %rsp, %rbp
    .LCFI1:
            movl    %edi, -4(%rbp)
            leaq    -4(%rbp), %rax
            decl    (%rax)
            movl    -4(%rbp), %eax
            leave
            ret
    

  • Mod

    ja, gcc macht sich eine eigenschaft zu nutze, die - architekturbedingt - nur sehr wenige andere befehle ebenfalls haben:
    das ziel der operation ist nicht gleichzeitig auch ein operand der operation - die verwendung von lea spart also einen mov-befehl ein.


Anmelden zum Antworten