Probleme mit GCC und Inline-Assembler in C-Programm



  • Hi!

    Ich brauche noch einmal Hilfe. Seit Stunden versuche ich ein C-Programm mit dem GCC unter Linux zum Laufen zu bringen, das Inline-Assember-Anweisungen enthält.
    Den GCC habe ich mit "gcc -o testprog tausch.c" aufgerufen.
    Der GCC akzeptiert aber die Syntax nicht.

    Nach einigen Anläufen habe ich es mit einem kleinen Testprogramm versucht, das
    zwei Werte vertauschen soll. Der Fehler ist prinzipiell derselbe.

    Hier ist ein Ausschnitt:

    unsigned short x=3, y=4;
    print("x=%d y=%d\n", x,y);
    __asm
    { <==== Fehlermeldung: pars error bevor '{' token
    mov ax, x
    xchg ax, y
    mov x, ax
    }

    print("x=%d y=%d\n", x,y);

    Kann mir jemand die richtige Schreibweise angeben?



  • gcc benutzt den at&t syntax für inline asm. ich glaub es gibt aber eine option um ihn auf intel syntax umzustellen, doch leider weis ich die nicht. aber google oder das manpage könnten dir weiterhelfen.



  • Der GCC benutzt eine komplett andere Inline-Assembler Syntax

    http://www-106.ibm.com/developerworks/linux/library/l-ia.html?dwzone=linux



  • Hallo!

    Zunächst mal herzlichen Dank für Eure Hilfe!

    Ich habe mich im Internet nach AT&T-Assembler umgesehen. Zur Zeit fühle ich mich mit der Portierung der Intel- in die AT&T-Schreibweise überfordert.
    Die Assemblerabschnitte, die ich brauche, sind doch länger als in dem kleinen Testprogramm, das ich anfangs angegeben hatte.

    Die Syntax des NASM ist mir da schon viel lieber. Inline-Assember mit NASM scheint aber ein größeres Problem zu sein. Vielleicht geht es mit Assembler-Routinen, die getrennt übersetzt werden können, einfacher.

    Ich habe bis jetzt sehr wenig Erfahrung mit Assembler-Programmierung für den PC.

    Bitte sagt mir doch, wie ich aus einem Inline-Assembler-Abschnitt eine Assembler-Routine mache, sie mit NASM übersetze und anschließend im C-Programm
    wieder einbinde.

    Vielleicht ist der kleine Ausschnitt ja eine Hilfe

    int main()
    {
    int x=3, y=4;
    print("x=%d y=%d\n", x,y);

    __asm
    { <==== Fehlermeldung: pars error bevor '{' token
    mov ax, x
    xchg ax, y
    mov x, ax
    }

    print("x=%d y=%d\n", x,y);
    return 0;
    }



  • Ich hoffe, du machst das nur, um zu probieren und nicht, um es "schneller" zu machen.



  • Hallo Ringding,

    es geht mir nicht darum ein Programm schneller zu machen.
    Ich will nur ein existierendes Programm (das nicht von mir ist) zum Laufen bringen, das Assembler-Anweisungen enthält.



  • Nachfolgend ein Beispiel mit asm in AT&T-Syntax, vielleicht hilft Dir das weiter:

    #include <iostream>
    #include <conio.h>
    using std::cout;
    using std::endl;
    
    //globale Variablen
    int a = 1; 
    int b = 2;
    
    void ausgabe()
    {
        cout << &a << ": " << a << "\t " << &b << ": " << b  << endl << endl;
    }
    
    void erfolgloser_swap( int x, int y )
    {
      cout << "Kopien auf dem Stack: " << endl;
      cout << &x << ": " << x << "\t " << &y << ": " << y << endl;
    
      int temp = x;
      x = y;
      y = temp;
    
      cout << &x << ": " << x << "\t " << &y << ": " << y << endl;
      cout << "swap nur lokal erfolgreich." << endl;
    }
    
    void zeiger_swap( int * x, int * y ) // C-Lösung
    {
      int temp = *x; // Inhalts-Operator // Dereferenzierungs-Operator
      *x = *y;
      *y = temp;
    }
    
    void referenzen_swap( int & x, int & y ) // C++-Lösung
    {
      int temp = x;
      x = y;
      y = temp;
    }
    
    int main()
    { 
        cout << "Ausgangssituation: " << endl;
        ausgabe();
    
        cout << "Tausch mittels std::swap(x,y): " << endl;            
        std::swap(a,b); // Methode der Wahl aus der STL
        ausgabe();
    
        cout << "Tausch mittels Zeiger: " << endl;            
        zeiger_swap(&a, &b);
        ausgabe();
    
        cout << "Tausch mittels Referenzen: " << endl;            
        referenzen_swap(a,b);
        ausgabe();
    
        cout << "Erfolgloser Tausch, da nur lokale Kopien getauscht werden." << endl;            
        erfolgloser_swap(a,b);
        ausgabe();
    
        cout << "Tausch mittels Register eax und ebx: " << endl;         
        //swap (a,b) 
        __asm("mov _b, %eax"); //AT&T Syntax bei Dev-C++ 
        __asm("mov _a, %ebx"); 
        __asm("mov %eax, _a"); 
        __asm("mov %ebx, _b"); 
        ausgabe(); 
    
        getch();
    }
    


  • Himmel Herrgott, wenn du irgendwelche Register verwendest, musst du das dem Compiler schon sagen (clobbers). Wie man das macht, steht in jedem GCC Inline Assembly HOWTO.

    Ich frag mich allerdings, wieso du dafür partout asm verwenden willst. Wenn dein Ziel ist, das Programm zum laufen zu kriegen, dann tausch doch einfach händisch die Variablen aus.



  • Danke an alle, die mir geholfen haben, besonders an Erhard Henkes - für die Beispiele!

    Leider hatte ich am Ende ein zusätzliches Hardware-Problem. Ich wollte ein altes Fischertechnik Interface in Betrieb nehmen.
    Die Assembleranweisungen waren in einer Routine für die Analag-Digitalwandlung.
    Weil das Programm getestet war, bin ich zunächst davon ausgegangen, dass es laufen würde. Nachdem sich die Sache mit dem Inline-Assembler als schwieriger heraus gestellt hat, habe ich sie mal vorübergehend auskommentiert, um zu sehen, ob das übrige funktioniert. Leider scheint die Hardware defekt zu sein. Tja, Pech.
    Jetzt muss ich mich erst mal darum kümmern.
    Danach werde ich mir den Assemblerteil noch mal in Ruhe ansehen.


Anmelden zum Antworten