Anfängerfrage in Sachen C und Assembler



  • Hi Leute!
    Und zwar will ich mit Variablen in C und Inline-Assembler arbeiten.
    Das hat was damit zu tun das ich in der Schule mit MASM 16Bit lernen soll etc.
    Da ich aber noch komplett wenig Ahnung davon habe bitte ich euch nen bissl geduldig mit mir zu sein 😉

    Um erstmal Grundlegend festzustellen wie es so grob funktioniert dachte ich mir erstmal 2 char-vars zu erstellen (var1 und var2) und per asm den Wert von var1 nach var2 zu kopieren. Danach soll einfach der Inhalt von var2 ausgegeben werden.

    Arbeiten tu ich unter Linux mit dem aktuellen GCC 4.4.2.
    Dazu benutze ich noch die Intel-Syntax.
    Heißt also mein compiling-comman heißt:
    gcc main.c -o assembly.c -masm=intel

    Liegt halt daran das wir noch mit dem altem MASM programmieren.

    Hier der Code:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        unsigned short var1 = 1,var2;
    
    asm("mov al,var1");
    asm("mov bl,al");
    asm("mov var2,bl");
    
    printf("%i/%i",var2,var1);
        return EXIT_SUCCESS;
    }
    

    Beim compilen bekomme ich dann folgende Fehlermeldungen:

    /tmp/ccUVBkBx.o: In function `main':
    main.c:(.text+0xf): undefined reference to `var1'
    main.c:(.text+0x17): undefined reference to `var2'
    collect2: ld gab 1 als Ende-Status zurück
    

    Kann mir bitte jemand von euch da weiterhelfen diese (wahrscheinlich sehr einfache und grundlegende) Sache zu begreifen?

    Vielen Dank im voraus!



  • short == 16Bit, AL und BL sind 8 Bit Register.

    unsigned char var1 = 1,var2;
    ...
    	mov al,var1
    	mov bl,al
    	mov var2,bl
    


  • Erstmal danke für deine Antwort!
    Habs auch mit deinem Ansatz probiert:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        unsigned char var1 = 1,var2;
    
    asm("mov al,var1");
    asm("mov bl,al");
    asm("mov var2,bl");
    
    printf("%c",var2);
        return 0;
    }
    

    Leider kommt aber trotzdem beim compilen:

    /tmp/ccDuZLCf.o: In function `main':
    main.c:(.text+0xf): undefined reference to `var1'
    main.c:(.text+0x17): undefined reference to `var2'
    collect2: ld gab 1 als Ende-Status zurück
    


  • versuch mal:
    al,[var1]
    mov bl,al
    mov [var2],bl



  • Kommt leider die gleiche Fehlermeldung.
    Will C vielleicht das ich in dem inline-assembler nur die Adresse der Variable angebe (main.c:(.text+0xf): undefined reference to `var1')?

    Wenn ja geht es mit

    asm("mov al,&var1");
    asm("mov bl,al");
    asm("mov &var2,bl");
    

    auch nicht:

    [mrc@Babyface Assembler]$ gcc  main.c -o assembly -masm=intel
    main.c: Assembler messages:
    main.c:8: Error: bad expression
    main.c:8: Error: junk `var1' after expression
    main.c:10: Error: bad expression
    main.c:10: Error: junk `var2' after expression
    


  • Hi,

    auf lokale Variablen kannst du so nicht zugreifen. Außerdem solltest du den Assemblerblock zu einem einzigem zusammenfassen. Und natürlich funktionert GCC Inline Assembler ganz anders.

    So geht es:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        unsigned char var1 = 45,var2;
    
    asm(
    	"mov al, %1\n"	// 1 = zweiter parameter
    	"mov bl, al\n"
    	"mov %0 ,bl\n" // 0 = erster parameter
    	: "=r"(var2) // ausgaben: var2 <-- erster parameter = %0
    	: "r"(var1) // eingaben: var1 <-- zweiter parameter = %1
    	: "eax", "ebx" // dein code verändert eax und ebx (al ist teil von eax, bl ist teil von ebx)
    );
    
    printf("%i/%i",var2,var1);
        return EXIT_SUCCESS;
    }
    

    Das ganze sieht hier sehr kompliziert aus, weil der Inline Assembler von GCC eine sehr mächtige Kontrollmöglichkeit durch die Spezifikation von Eingabe, Ausgabe und Clobbers ermöglicht.

    Siehe auch:
    * Handbuch http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Extended-Asm http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints
    * ein HOWTO http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
    * und natürlich Google http://www.google.de/search?hl=de&site=&q=gcc+inline+assembler&btnG=Suche&meta=

    Über MASM lernst du damit eher nichts, weil der GCC und GAS halt komplett anders sind. Erstmal 32 statt 16 Bits, andere Syntax, andere Fehlermeldungen, etc... Höchstens von Assembler im Allgemeinen kannst du da was lernen.

    Das ist natürlich an sich nicht schlecht, vor allem weil sich mit dem Inline Assembler von GCC viele nette Sachen machen lassen. Aber ich weiß nicht, ob du damit in der Schule was anfangen kannst.



  • Hey du!
    Vielen Dank für deine Antwort!
    Ich hab es kurz vorher auch gelöst(es gibt ja Beispiele hierfür).
    ->http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

    Was aber für die Schule wichtig ist war ein Debugger deswegen programmieren wir MASM 16Bit mit einem altem Tool um die Register der CPU auszulesen.
    Ich habe aber für mich Code::Blocks mit einer sehr schönen Debugging-möglichkeit gefunden. Hier kann man sich halt die Register für 32Bit ansehen (also eax,ebx etc).
    Mit deiner Lösung werden aber leider alle Assembler-Befehle mit einem mal ausgeführt. Deswegen würde der Debugger wenig bringen. Da springt eax kurz auf 45 und das wars schon.
    Meine Lösung ist auf alle Fälle weniger elegant. Aber es geht eher darum zu verstehen WAS überhaupt in den Registern passiert.

    Hier der Code für 16Bit (ACHTUNG INTEL-SYNTAX (-masm=intel)):

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    unsigned char x = 10, y=0;
    
    asm("mov al,%0\n"  : :"r"(x));
    asm("mov bl,al\n");
    asm("mov %0,bl\n" :"=r"(y));
    
    printf("%i/%i",x,y);
        return 0;
    }
    

    Und hier für 32Bit (ACHTUNG AT&T-SYNTAX (-masm=att)):

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
     int a=10, b;
    asm("movl %0, %%eax;"::"r"(a));
    asm("movl %eax,%ebx");
    asm("movl %%ebx,%0":"=r"(b):);
    
    printf("%i/%i",a,b);
        return 0;
    }
    

    Ich frage mich bloß noch wie das alles für 64Bit ausehen würde ^^



  • in 64 bit bekommen die Register einfach ein R anstatt ein E z.B. aus EAX wird RAX...


Anmelden zum Antworten