Anfängerfrage: Wie greife ich auf Variablen eines C-Programms zu?



  • HAllo, ich fange gerade an Assembler zu Programmieren. Ich verwende dazu gcc.
    Ich habe folgendes Problem:
    Ich schreibe ein C-Programm, in dem Assembler vorkommen soll:

    int main(int argc, char *argv[])
    {
        int a=1,b=2;
        printf("a=%d b=%d",a,b);
    
    asm (
             "movl $a,%eax\n\t"
             "movl $b,%ebx\n\t"
             "movl %ebx,$a\n\t"
             "movl %eax,$b\n\t"         
        );
    
        printf("Nach dem Tauschen: a=%d b=%d",a,b); 
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    Wie ihr seht, möchte ich die Werte von a und b im Assemblercode vertauschen.
    Dazu müsste ich auf die Variablen zugreifen können. Leider funktioniert es Leider nicht. (Fehlermeldung: "suffix or operands invalid for mov") Heißt also ich habe irgend nen Syntaxfehler. Wie spreche ich denn Variablen des C-Programms aus dem Assembler heraus an? (Hab leider nix wirklich sinnvolles gefunden via Google 😞 )

    PS: Gibt es eine Möglichkeit bei gcc, dass man nicht immer den Code in Anführungszeichen und mit \n\t am Ende schreiben muss, sondern mehr in der Art
    movl $b,%eax ?

    Danke
    S.W.



  • XCooperation schrieb:

    (Hab leider nix wirklich sinnvolles gefunden via Google 😞 )

    Ich schon. Und zwar als ersten Link:

    http://www.krucker.ch/Skripten-Uebungen/InfUeb/Assembler%20in%20C-CPP%20Programmen.pdf


  • Mod

    im gegensatz zu zu z.b. msvc ist die übersetzung bei gcc deutlicher in einzelne phasen aufgeteilt. inline assembler code ist für den compiler wie ein funktionsaufruf, über den den compiler nichts weiter weiß - im gegensatz zu echten externen funktionen (von denen der compiler annehmen muss, dass sie beliebige nebeneffekte haben können - es sei denn, durch __attribute__ eingeschränkt) kann man diese seiteneffekte allerdings sehr genau durch input/output und clobberliste spezifizieren, dies ist auch für den optimierer wichtig, soweit es darum geht, code umzuordnen. entscheidend dabei ist, dass der der code C bzw. c++ code bereits übersetzt wurde, bevor der inline assembler code überhaupt berücksichtigt wird (er wird einfach 1:1 in den gas input übernommen). zu diesem zeitpunkt existieren aber keine lokalen symbole mehr. um dennoch auf lokale variablen zugreifen zu können, müssen diese als input oder output gelistet werden. durch constraints kann hier spezifiziert werden, wo der betreffende input erwartet wird (register/speicher/immediate etc.). ein simpler inline assembler swap muss z.b. gar keinen code enthalten: 😉

    int main()
    {
        int a=1,b=2;
        printf("a=%d b=%d",a,b);
    
    asm ( "" : "r" ( a ), "r" ( b ) : "=1" ( a ), "=0" ( b ) );
    
        printf("Nach dem Tauschen: a=%d b=%d",a,b);
    }
    

    (ungetestet)

    da der inline code 1:1 als input für gas erscheint, kann zumindest auf \n (bis auf das letzte) nicht verzichtet werden. um die lesbarkeit zu erhöhen, könnte man es allerdings ohne weiteres anders formatieren:

    asm (
      "fooop %1,%2"             "\n\t"
      "barop %2,%1"             "\n\t" );
    

    ein #define für "\n\t" könnte hier sinnvoll sein



  • Danke erstmals 😉
    Also, das mit Swap funktioniert ja schon ganz schön. Jetzt probier ich gerade an MMX herum (das ist ja auch mein Ziel):

    asm (
             "movq _a,%mm0           \n\t"
             "pshufw %mm0,%mm0,$1    \n\t"
             );
    

    Allerdings kommt hier der Fehler :
    suffix or operands invalid for `pshufw'
    Müsste aber doch richtig sein oder?

    PS: Was oben falsch war:
    So ists richtig:

    asm (
             "movl _a,%eax\n\t"
             "movl _b,%ebx\n\t"
             "movl %ebx,_a\n\t"
             "movl %eax,_b\n\t" 
        );
    

    Allerdings kann man so nur auf globale Variablen zugreifen, und nicht auf lokale (deswegen hats bei mir nicht funktioniert 😉 )

    Mit diesem Code kann man auch auf lokale Variablen zugreifen und man bekommt auch keine Probleme mit Registern:

    asm (
             "movl %0,%%eax\n\t"
             "movl %1,%%ebx\n\t"
             "movl %%ebx,%0\n\t"
             "movl %%eax,%1\n\t" 
             :"=r" (a), "=r" (b)
             :"0" (a), "1" (b)
             :"%eax","%ebx"  
        );
    

    Am besten ist natürlich der Code von camper

    DarthZiu schrieb:

    XCooperation schrieb:

    (Hab leider nix wirklich sinnvolles gefunden via Google 😞 )

    Ich schon. Und zwar als ersten Link:

    http://www.krucker.ch/Skripten-Uebungen/InfUeb/Assembler%20in%20C-CPP%20Programmen.pdf

    Jop, das hab ich auch gefunden, aber wenn du gaaaanz genau hinsiehst fällt dir da was auf? Ich benutze gcc und der benutzt leider nicht den Intel-Syntax sondern AT&T Syntax (glaub ich das der so heißt) 😉



  • OK, ein bisschen herumgespielt, und an was lags...
    Die Reihenfolge der Argumente ist hier anderst als wie in der Intel-Syntax 🙄

    asm (
             "movq _a,%mm0         \n\t"
             "pshufw $1,%mm0,%mm0  \n\t"
             );
    

    Trotzdem noch eine Frage:
    Bei Intel gibts eine Syntax, mit der man Binärzahlen angeben kann:
    010101b, zum Beispiel.
    Gibts das auch bein gcc?


Log in to reply