Erste Schritte mit Assembler

  • Erste Schritte mit Assembler

    Hallo,

    Ich mache gerade (gezwungenermassen) meine ersten Schritte mit Assembler und stosse da schon auf die ersten Hindernisse:

    Quellcode

    1. #include <stdio.h>
    2. void sum(int, int, int *);
    3. int main (int argc, const char * argv[]) {
    4. int a, b, *r;
    5. a = 2; b = 3; *r = 0;
    6. sum(a, b, r);
    7. printf("%i", *r);
    8. return 0;
    9. }
    10. void sum(int a, int b, int *res)
    11. {
    12. asm("movl 8(%ebp), %eax; movl 12(%ebp), %ebx; movl 16(%ebp), %ecx; leal (%eax, %ebx), %edx; movl %edx, (%ecx);"); // *res = a + b
    13. }
    Alles anzeigen


    Wenn ich das ganze nun ausführe schaltet sich bei printf der gdb dazu (a = 2, b = 3, *r = 5). Ich verstehe allerdings nicht so recht wieso? Kann ich denn innerhalb einer Funktion etwas von der Aussenwelt kapput machen?

    Btw: Zu rückgabewerten bin ich noch nicht gekommen, deshalb hab ich das mit einem Pointer gemacht.

    Noch ein paar allgemeine Fragen zu Assembler in Xcode:

    1. Kann ich das asm() statement irgendwie schön darstellen? Ich find's ja schon verwirrend genug, da muss nicht unbedingt auch noch alles auf einer Linie stehen.

    2. Kann ich mir den Assembler-Code in Xcode schön darstellen lassen? Unter Build -> Show assembly code sieht meine Funktion irgendwie komisch aus:



    Quellcode

    1. _sum:
    2. .stabd 46,0,0
    3. .stabd 68,0,17
    4. nop
    5. nop
    6. nop
    7. nop
    8. nop
    9. nop
    10. pushl %ebp
    11. movl %esp, %ebp
    12. subl $8, %esp
    13. .stabd 68,0,18
    14. movl 8(%ebp), %eax; movl 12(%ebp), %ebx; movl 16(%ebp), %ecx; leal (%eax, %ebx), %edx; movl %edx, (%ecx);
    15. .stabd 68,0,19
    16. leave
    17. ret
    18. .stabs "sum:F(0,1)",36,0,17,_sum
    19. .stabs "a:p(0,2)",160,0,16,8
    20. .stabs "b:p(0,2)",160,0,16,12
    21. .stabs "res:p(0,7)",160,0,16,16
    Alles anzeigen


    Könnte ein paar Tipps gebrauchen, Danke.
    Gruss Dominik.
  • So, jetzt hab ich was funktionierendes:

    Quellcode

    1. #include <stdio.h>
    2. int fn(int);
    3. int main (int argc, const char * argv[]) {
    4. int a = 2;
    5. int b;
    6. b = fn(a);
    7. printf("%d -> %d\n", a, b);
    8. return 0;
    9. }
    10. int fn(int a)
    11. {
    12. asm("movl 8(%ebp),%eax; subl $19,%eax");
    13. }
    Alles anzeigen


    wobei jetzt auch der Assembler-Code so aussieht wie ich das erwarte (das leave ist jetzt nicht mehr da):

    Quellcode

    1. _fn:
    2. .stabd 46,0,0
    3. .stabd 68,0,17
    4. nop
    5. nop
    6. nop
    7. nop
    8. nop
    9. nop
    10. pushl %ebp
    11. movl %esp, %ebp
    12. .stabd 68,0,18
    13. movl 8(%ebp),%eax; subl $19,%eax
    14. .stabd 68,0,19
    15. popl %ebp
    16. ret
    17. .stabs "fn:F(0,2)",36,0,17,_fn
    18. .stabs "a:p(0,2)",160,0,16,8
    19. .stabs "int:t(0,2)=r(0,2);-2147483648;2147483647;",128,0,0,0
    Alles anzeigen


    Jetzt kann ich wenigstens mal ein wenig damit rumspielen. Seh ich das richtig das all die .stabs für den Debugger da sind?
    Gruss Dominik.
  • und gleich noch eine Frage hinterher:

    Quellcode

    1. int powerOfTwo(int a)
    2. {
    3. asm("movl 8(%ebp),%edx; movl $1,%eax; sall %edx,%eax");
    4. }


    compiliert nicht mit dem Fehler

    Quellcode

    1. /var/tmp//cc1Sbd3v.s:6:suffix or operands invalid for `sal'


    während das ganze mit einer fixen Potenz

    Quellcode

    1. int powerOfTwo(int a)
    2. {
    3. asm("movl 8(%ebp),%edx; movl $1,%eax; sall $2,%eax");
    4. }


    einwandfrei funktioniert!? Ach ja, wenn ich in Xcode die Build-Configuration auf Release stelle kompiliert auch plötzlich gar nichts mehr? Das hat aber weniger mit meinem aktuellen Problem zu tun, damit kann ich leben ;)
    Gruss Dominik.
  • Generell solltest du aufpassen, wie die Register belget werden. Lies dazu die entsprechenden Docs von Apple zur Mach-O Function Call ABI...

    Bei i386_64 sieht die Registerbelegung GANZ anders aus.

    Richtigerweise müsstest du die hässliche und oft unverständliche gcc Schreibweise benutzen, dann kannst du Inline-Assembler auch parametrisieren und der gcc sorgt dafür, dass die Werte da sind, wo du sie brauchst. Leider ist das relativ schlecht dokumentiert und erschließt sich auch nicht auf Anhieb.

    Ich habe mich damit auch heftig rumärgern müssen...
  • Original von ssb
    Generell solltest du aufpassen, wie die Register belget werden. Lies dazu die entsprechenden Docs von Apple zur Mach-O Function Call ABI...


    Danke, werd ich mir bei gelegenheit und wenns nicht all zu viel ist mal antun :) Ich weiss mittlerweile, das mein Programm abschmiert, wenn ich was in %ebx schreibe.

    Original von ssb
    Bei i386_64 sieht die Registerbelegung GANZ anders aus.


    Naja, damit muss ich mich glücklicherweise noch nicht beschäftigen...

    Original von ssb
    Richtigerweise müsstest du die hässliche und oft unverständliche gcc Schreibweise benutzen, dann kannst du Inline-Assembler auch parametrisieren und der gcc sorgt dafür, dass die Werte da sind, wo du sie brauchst. Leider ist das relativ schlecht dokumentiert und erschließt sich auch nicht auf Anhieb.


    Meinst du mit hässlicher gcc Schreibweise und parametrisieren sowas hier?

    Quellcode

    1. int a=10, b;
    2. asm ("movl %1, %%eax;
    3. movl %%eax, %0;"
    4. :"=r"(b) /* output */
    5. :"r"(a) /* input */
    6. :"%eax" /* clobbered register */
    7. );


    Oder muss ich mir noch mehr antun?
    Gruss Dominik.