2009-09-27 35 views
1

如何直接調用「printf」而不包括stdio.h?一個簡單的C程序沒有#include <stdio.h>

我發現了一個有趣的教程在這裏:
http://www.halcode.com/archives/2008/05/11/hello-world-c-and-gnu-as/

所以,這裏是我的嘗試:

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; 
} 

我使用MinGW的4.4,這裏是我如何編譯:

gcc -c hello.c -o hello.o
ld hello.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

不幸的是,它失敗:

hello.o:hello.c的:(文字+ 0×26) :未定義的參考'ss'

如何解決這個問題?

+0

爲什麼你需要? – 2009-09-27 09:44:38

+2

@艾哈邁德 - 正在學習禁止?知識的獲取是不是皺起了眉頭? – 2009-09-27 09:45:43

+0

好吧,只是純粹的好奇心 我幾乎知道它並不重要 – anta40 2009-09-27 09:46:23

回答

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

這一個適用於我..社區wiki做了不是很好! – abelito 2012-07-04 03:51:12

+0

什麼是'__asm()'? – theonlygusti 2014-12-26 17:01:24

+0

@theonlygusti __asm()允許你調用內聯彙編代碼,在操作系統編程中最常見(我想真的是看到任何彙編代碼的最常見的地方)。一個體面的寫在它:http://wiki.osdev.org/Inline_Assembly – rady 2015-03-20 14:19:14

8

您可以將printf的聲明覆制到您的程序中。在C中,包括其他文件只是將其文本粘貼到程序中。所以你可以通過自己做複製粘貼來完成這項工作。

extern int printf (const char* format, ...); 

int main() 
{ 
    printf("Hello, world!\n"); 
    return 0; 
} 

鏈接一定會發現在圖書館的正確定義,對你的程序在默認情況下鏈接。

+0

雖然這適用於回答OP的問題,但它完美地忽略了OP的意圖,這更符合如何使用GCC進行內聯彙編的工作,而不是使用不包含標題的函數。 – 2009-09-27 10:03:56

+0

@Paul 哇,它的工作原理。我從來沒有想過這樣的事情是可能的 @Chris 是的,你是對的。對不起,我的誤導標題。 – anta40 2009-09-27 10:27:15

+0

@Chris Lutz:嘿,不要把我描述爲欺詐! :-)我以我理解的方式回答。無論如何,我的一個人接受了第二個被接受的答案。 :-) – 2009-09-27 10:42:42

2
int main() { 

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

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

    return 0; 
} 
+0

這被稱爲內聯彙編。更多信息在這裏:http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html – LiraNuna 2009-09-27 10:39:20

+1

這是危險的在線組裝。 %esp指向堆棧的頂層元素,而不是下一個空閒元素。就像那樣,你可能會在堆疊頂部重新打折。你應該推動arg然後彈出它。 – Falaina 2009-09-27 10:47:21

+0

doh!你是對的。 Ofcource然後我們必須解釋OP調用約定。 :*> – 2009-09-27 11:24:47

-3

它使用printf語句然後 保存擴展名爲.c 程序和運行程序 它將工作很輕鬆 寫一個C程序.... 即使它可以包含類似的功能clrscr(),getch()哪些是conio.h的一部分