Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一个没有#include<;标准h>;_C_Assembly_Printf_Mingw_Inline Assembly - Fatal编程技术网

一个没有#include<;标准h>;

一个没有#include<;标准h>;,c,assembly,printf,mingw,inline-assembly,C,Assembly,Printf,Mingw,Inline Assembly,如何直接调用“printf”而不包括stdio.h 我在这里找到了一个有趣的教程: 因此,以下是我的尝试: int main(){ char ss[] = "hello"; asm ( "pushl %ebp ;" "movl %esp, %ebp ;" "subl $4, %esp ;" "movl $ss, (%esp) ;" "call _printf ;" "movl $0, %eax ;" "leave ;" "ret ;" ); ret

如何直接调用“printf”而不包括stdio.h

我在这里找到了一个有趣的教程:

因此,以下是我的尝试:

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
你好 -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:(.text+0x26):对“ss”的未定义引用


如何修复此问题?

您可以将
printf的声明复制到您的程序中。在C语言中,包含其他文件只是将其文本粘贴到程序中的一个副本。因此,您可以通过自己进行复制粘贴来完成这项工作

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

int main()
{
  printf("Hello, world!\n");
  return 0;
}
链接器肯定会在库中找到正确的定义,默认情况下,您的程序是根据这些库链接的。

非常容易
int main() {

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

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

    return 0;
}
然后使用printf语句编写一个c程序 用.c扩展名保存程序 然后运行程序 它会起作用的。。。。
甚至它也可以包含CLRSC()、getch()等函数,这些函数都是conio.h的一部分

为什么需要呢?@Ahmed-禁止学习吗?不赞成获取知识吗?好吧,纯粹出于好奇,我知道实际上这并不重要,你不能把汇编程序的输出粘贴到C程序中。例如,您的“ret”只是一个返回语句。asm块中的前2-3行设置堆栈,您不应该在c程序中执行此操作,因为CRT已经为每个函数插入了这样的代码。虽然这有助于回答OP的问题,但却完全忽略了OP的意图,这更像是如何使用GCC进行内联汇编,而不是在不包含头的情况下使用函数。@Chris Lutz:嘿,别把我描述成骗子!:-)我用我理解的方式回答。不管怎样,我的答案在被接受后有一个很好的第二个答案。:-)@anta40,这就是当你坚信一些语言特性,如#包含do magic,这就是所谓的内联汇编。更多信息:这是危险的在线组装esp指向堆栈的顶部元素,而不是下一个自由元素。你可能已经像那样击打了堆栈顶部的任何东西。你应该按下arg然后在后面弹出它。doh!你说得对。当然,我们必须向OP呼叫约定解释。:*>这也行。非常感谢。是的,我仍然需要学习那些电话会议,因为我是一个业余爱好者。顺便说一句,当把ss改成“helloworld”时,输出是“.为什么?看看Christoph的例子-他也从stack@theonlygusti__asm()允许您调用内联汇编代码。在操作系统编程中最常见(我想这是最常见的汇编代码)这里有一个不错的评论:@rady哪种语言?你的电脑的?还是它使用了其他语言?
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);
    */
}