Inline Assemler mit GCC unter Verwendung der Intel Syntax



  • Ich habe ein Problem mit GCC 3.4.5 unter Windows bei Verwendung von Assembleranweisungen in Intel Syntax.

    Der Code ist folgender:

    /* asm_test.c */
    #include <stdio.h>
    
    int main()
    {
      int i = 0;
      asm(".intel_syntax noprefix\n"
          "mov eax, dword ptr i\n"
          "inc eax\n"
          "mov dword ptr i, eax\n"
      );
      printf("Ergebnis: %i\n", i);
      return 0;
    }
    

    Die erste Assembleranweisung soll den Inhalt der C Variable i in das EAX Register laden, dann einmal den Wert um 1 erhöhen und dann das Ergebnis in die C Variable i zurückkopieren.

    Und genau da, an der Übergabe von Variablen vom C Code in den Assembler Code hakt es.

    Als Fehlermeldung erhalte ich immer einen Fehler wie z.B. diesen da:

    ..\LOKALE~1\Temp/cc4dVMYU.o:asm_test.c:(.text+0x32): undefined reference to `i'
    

    Compiliert wird das ganze so:

    gcc -masm=intel asm_test.c -o asm.exe
    

    Die \n am Ende jeder Assembleranweisung sind bei mehreren Assemblerbefehlen notwendig.

    Die GCC-Inline-Assembly-HOWTO war gar keine Hilfe oder ist fehlerhaft:
    http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

    Dort steht z.B. unter Abschnitt 3. 4. Operand Size folgendes Beispiel:

    Thus, Intel "mov al, byte ptr foo" is "movb foo, %al" in AT&T syntax.

    In C Code eingebaut sieht das Beispiel dann so aus:

    /* asm_howto.c */
    #include <stdio.h>
    
    int main()
    {
      char foo = 0;
      asm("mov al, byte ptr foo");
      return 0;
    }
    

    Aber auch hier erhalte ich die gleiche Fehlermeldung.

    Vor dem Variablennamen im Assembler Code ein _ oder $_ (AT&T Syntax) dranzumachen, also anstatt i, _i oder $_i zu schreiben, hat ebenfalls keinen Erfolg gebracht.

    Anstatt asm(), __asm__() zu schreiben ändert übrigens auch nichts am Ergebnis.

    Und der Artikel im FAQ Bereich hier im Forum half ebenfalls nicht.
    Der in der FAQ angegebene Intel Syntax Code funktioniert nämlich leider auch nicht.
    http://www.c-plusplus.net/forum/41479

    Wichtig:
    Ich möchte wirklich wissen wie das obige mit Intel Syntax geht.
    Beispiele in AT&T Syntax helfen also nicht.



  • Das Problem ist nicht die Intel Syntax, sondern das du nicht einfach Variablennamen im inline Assembler nutzen kannst. Guck dir mal in dem Hotwo Kapitel 5 und besonders 5.3 die Clobber List an. Da gibst du an welche Variablen gelesen/geschrieben werden, und ob diese aus dem Speicher, aus Registern oder sonst wo kommen.



  • Tobiking2 schrieb:

    Das Problem ist nicht die Intel Syntax, sondern das du nicht einfach Variablennamen im inline Assembler nutzen kannst. Guck dir mal in dem Hotwo Kapitel 5 und besonders 5.3 die Clobber List an. Da gibst du an welche Variablen gelesen/geschrieben werden, und ob diese aus dem Speicher, aus Registern oder sonst wo kommen.

    Ach so, ich kenne Inline Assembler bisher leider nur vom MS Compiler und da ging das mit der Verwendung von Variablennamen im Assemblerteil.
    http://msdn.microsoft.com/en-us/library/ydwz5zc6(v=vs.71).aspx

    Daher danke für den Hinweis, ich werde mir das Kapitel mal durchlesen.



  • Hm, funktioniert irgendwie nicht:

    #include <stdio.h>
    
    int main()
    {
      int i = 0;
    
      __asm__ (".intel_syntax noprefix\n"
          "mov eax, dword ptr i\n"
          "inc eax\n"
          "mov dword ptr i, eax\n"
          :"0"(i)        // input & output
      );
      printf("Ergebnis: %i", i);
      return 0; 
    }
    


  • So, jetzt wird der Wert wenigstens an den C Code zurückgegeben, aber der Übertrag vom C Code in den Assemblercode funktioniert noch nicht:

    #include <stdio.h>
    
    int main()
    {
      int i = 0;
    
      __asm__ (".intel_syntax noprefix\n"
          "mov eax, dword ptr %0\n"
          // "mov eax, 10\n"
          "inc eax\n"
          "mov dword ptr %0, eax\n"
          : "=a" (i)
      );
      printf("Ergebnis: %i", i);
      return 0; 
    }
    

    Eigentlich sollte als Ergebnis eine 1 ausgegeben werden, aber stattdessen wird eine 2 ausgegeben.

    Wenn ich das EAX Register aber Testweise mit einem bestimmten Wert inialisiere, z.B. 10, dann wird richtig gerechnet und das richtige Ergebnis, in diesem Falle 11 ausgebeen.

    Das Problem liegt also noch irgendwo bei der Datenübergabe vom C Code nach Assembler.
    Das EAX Register hat hier aus irgendeinem Grund den Wert 2, obwohl es eigentlich den Wert 0 durch den ersten mov Befehl bekommen sollte, denn die Variable i hat ja den Anfangswert 0.



  • Juhuu, ich hab's:

    #include <stdio.h>
    
    int main()
    {
      int i = 0;
    
      __asm__ (".intel_syntax noprefix\n"
          "mov eax, dword ptr %0\n"
          "inc eax\n"
          "mov dword ptr %0, eax\n"
          : "=o" (i)
      );
      printf("Ergebnis: %i", i);
      return 0; 
    }
    

    Beim Constraint habe ich leider anstatt einem Kleinbuchstaben o die Zahl 0 benutzt.



  • also wenn du i global deklarierst, dann gehts auch "einfacher"

    /* asm_test.c */
    #include <stdio.h>
    
    int i = 0;
    
    int main()
    {
      asm("mov eax, dword ptr _i\n"
          "inc eax\n"
          "mov dword ptr _i, eax\n"
      );
      printf("Ergebnis: %i\n", i);
      return 0;
    }
    

    und zwar muss man _ vor den variablen namen setzen.
    und das ".intel_syntax noprefix" kann man sich sparen, einfach -masm=intel als parameter verwenden.

    so sieht es eig, schöner aus, wenn die variable nicht global sein müsste 😕 einer eine idee??

    mfg


Anmelden zum Antworten