assebmler in C einbinden



  • Hey leute,

    kurze frage. wie bindet man eigentlich assembler code in C ein?
    man sagt ja zB die meisten betriebssysteme sind zum großteil in C und assembler geschrieben. wie hat man den fertigen code dieser beiden sprachen miteinander verbunden?

    danke im voraus und gruß an alle 😉



  • Die meisten Compiler lassen Inline-Assembler zu, das hat sogar der Standard bemerkt:

    C99 schrieb:

    J.5 Common extensions
    ...
    The asm keyword may be used to insert assembly language directly into the translator
    output (6.8). The most common implementation is via a statement of the form:
    asm ( character-string-literal );

    Bei Mircosoft heisst es (glaub ich) __asm .

    die meisten betriebssysteme sind zum großteil in C und assembler geschrieben

    Nicht zum Grossteil, sondern: ausschliesslich. Von den beiden wiederum ist der Grossteil in C.

    wie bindet man eigentlich assembler code in C ein?

    Man muss nicht inlinen. Wenn man die Aufrufkonventionen des Compilers kennt, kann man ja einfach eine Objekt-Datei mit Assembler bauen, und dann mitlinken.



  • lustigerweise hatte ich genau so etwas heute versucht, doch es ist mir nicht gelungen, denn es gibt immer einen Laufzeitfehler. So sah mein Ansatz aus:

    C-Datei:

    #include <stdio.h>
    
    int __stdcall my_add(int, int); // Assembler Funktion deklarieren; stdcall-Convention verwendet
    
    int main()
    {
      printf("%d", my_add(4, 5)); // Aufruf der Funktion
    }
    

    asm-Datei:

    .globl _my_add
    
    _my_add:
    
    popl %eax
    popl %ebx
    
    addl %ebx,%eax
    
    ret
    

    Mein Compiler ist der gcc 3.4.5 (MinGW).
    Die asm-Datei muss man zuerst mit dem Assembler (as) in eine o-Datei umwandeln und dann kann man sie einfach dazulinken.



  • Laut Wikipedia (http://en.wikipedia.org/wiki/X86_calling_conventions#stdcall) sind nur die Register eax, ecx und edx dazu gedacht von der Funktion geändert zu werden. Der gcc dürfte also nicht damit rechnen das der in ebx abgelegte Wert nicht mehr der ist der es sein soll.



  • vielen dank für den Hinweis, doch leider schmiert er immer noch ab 😞 .



  • vielen dank schonmal für die hilfen.

    vllt noch eine etwas dumme frage: wann verwendet man genau ".globl"??



  • Wie lautet der Laufzeitfehler? Hast du es mal mit einem Debugger probiert?



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Nicht zum Grossteil, sondern: ausschliesslich. Von den beiden wiederum ist der Grossteil in C.

    Ich möchte keinen Diskussion anzetteln, aber sobald es sich vom absoluten Low-Level entfernt wird genug in C++ geschrieben.



  • es kommt die xp typische meldung das programm xyz hat ein Problem festgestellt und muss beendet werden.

    Den Debugger hab ich noch nicht benutzt, da ich mir nicht sicher bin ob er auch mit assembler funktioniert.



  • player4245 schrieb:

    es kommt die xp typische meldung das programm xyz hat ein Problem festgestellt und muss beendet werden.

    ich denke da fehlt noch was (auf'm stack und so). zweimal 'pop' und ein 'ret' zum schluss, sehen irgendwie falsch aus. mach dir doch eine äquivalente C-funktion und schau dir an, welchen asm-code der compiler ausspuckt.

    Icematix schrieb:

    aber sobald es sich vom absoluten Low-Level entfernt wird genug in C++ geschrieben.

    das war mal schlimmer, mittlerweile hält es sich in grenzen. *fg*
    🙂



  • hab mir mal den asm output der funktion geholt, natürlich auch mit stdcall-convention. Das ist was der Compiler drauß macht:

    .file	"add.c"
    	.text
    .globl _add@8
    	.def	_add@8;	.scl	2;	.type	32;	.endef
    _add@8:
    	pushl	%ebp ; Alten stand vom Base-Pointer sichern
    	movl	%esp, %ebp ; Bas-Pointer zur Stack-Spitze verschieben
    	movl	12(%ebp), %eax ; Parameter b in Register eax schreiben
    	addl	8(%ebp), %eax ; Und Parameter a dazuaddieren
    	popl	%ebp ; Alter Stand vom Base-Pointer wiederherstellen
    	ret	$8
    

    ich hab das ganze mal kommentiert damit man schneller durchsteigt 😉 .


Anmelden zum Antworten