2009-09-27 12 views
1

Comment appeler "printf" directement sans inclure stdio.h?Un simple programme C sans #include <stdio.h>

J'ai trouvé un tutoriel intéressant ici:
http://www.halcode.com/archives/2008/05/11/hello-world-c-and-gnu-as/

Alors, voici ma tentative:

int main(){ 
char ss[] = "hello"; 

asm (
    "pushl %ebp ;" 
    "movl %esp, %ebp ;" 
    "subl $4, %esp ;" 
    "movl $ss, (%esp) ;" 
    "call _printf ;" 
    "movl $0, %eax ;" 
    "leave ;" 
    "ret ;" 
); 

return 0; 
} 

J'utilise MinGW 4.4, et voici comment je le compiler:

gcc -c bonjour.c -o bonjour.o
ld bonjour.o -o hello.exe C:/mingw/lib/crt2. o C: /mingw/lib/gcc/mingw32/4.4.0/crtbegin.o C: /mingw/lib/gcc/mingw32/4.4.0/crtend.o -LC:/mingw/lib/gcc/mingw32 /4.4.0 -LC:/MinGW/lib -lmingw32 -lgcc -lmsvcrt -lkernel32

Malheureusement, il échoue:

hello.o. hello.c :(texte + 0x26) : référence non définie à `ss '

Comment résoudre ce problème?

+0

pourquoi devriez-vous? –

+2

@Ahmed - L'apprentissage est-il interdit? L'acquisition des connaissances est-elle désapprouvée? –

+0

bien, juste de la pure curiosité Je sais pratiquement que ce n'est pas important – anta40

Répondre

4
int main(void) 
{ 
    char ss[] = "hello"; 

    __asm(
     "pushl %[ss]\n" // push args to stack 
     "call _puts\n" 
     "addl $4, %%esp\n" // remove args from stack 
     :: [ss] "r" (ss) // no output args, no clobbered registers 
    ); 

    /* C equivalent: 
     extern int puts(const char *); 
     puts(ss); 
    */ 
} 
+0

Celui-ci fonctionne pour moi .. le wiki de la communauté a fait – abelito

+0

Qu'est-ce que '__asm ​​()'? – theonlygusti

+0

@theonlygusti __asm ​​() vous permet d'appeler le code de montage en ligne.Plus souvent vu dans la programmation OS (je pense vraiment l'endroit le plus commun pour voir tout code d'assemblage). une description décente à ce sujet: http://wiki.osdev.org/Inline_Assembly – rady

8

Vous pouvez copier la déclaration de printf dans votre programme. En C, y compris d'autres fichiers est un simple copier-coller son texte dans votre programme. Donc, vous pouvez faire ce travail en faisant le copier-coller sur votre propre. Linker trouvera sûrement la bonne définition dans les bibliothèques, par rapport auxquelles vous programmez est lié par défaut.

+0

Bien que cela fonctionne pour répondre à la question du PO, il manque nettement l'intention du PO, qui est plus sur la façon de travailler avec l'assemblage en ligne avec GCC que d'utiliser une fonction sans inclure un en-tête. –

+0

@Paul Ouah ça marche. Je n'ai jamais pensé qu'une telle chose était possible @Chris Oui, vous avez raison. Désolé pour mon titre trompeur. – anta40

+0

@Chris Lutz: hé, ne me dépeignez pas comme une fraude! :-) J'ai répondu de la façon dont j'ai compris. Quoi qu'il en soit, le mien fait une bonne réponse après l'autre. :-) –

2
int main() { 

    char ss[] = "hello"; 
    char *p = ss; 

    asm (
     "movl %0, (%%esp);" 
     "call _printf;" : "=r" (p) 
    ); 

    return 0; 
} 
+0

Ceci s'appelle l'assemblage en ligne.Plus d'informations ici: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html – LiraNuna

+1

C'est dangereux montage en ligne. % esp pointe vers l'élément supérieur de la pile PAS l'élément libre suivant. Vous avez peut-être bousillé tout ce qui est en haut de la pile comme ça. Vous devriez appuyer sur l'argument puis le pop après. – Falaina

+0

doh! Tu as raison. Ofcource alors nous aurions à expliquer aux conventions d'appel OP. : *> –

-3

Sa très facilité Ecrire un programme c en utilisant printf puis enregistrer le programme avec l'extension .c et exécuter le programme Il fonctionnera .... Même il peut contenir fonction comme clrscr(), getch() qui font partie de conio.h