Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.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
Linux 从_start调用printf时链接器错误_Linux_Assembly_X86 64_Linker Errors_Ld - Fatal编程技术网

Linux 从_start调用printf时链接器错误

Linux 从_start调用printf时链接器错误,linux,assembly,x86-64,linker-errors,ld,Linux,Assembly,X86 64,Linker Errors,Ld,我试着在没有主键的情况下编写简单的程序 汇编: yasm -f elf64 main.s; ld -o main main.o 得到 如何解决这个问题?C标准库libc提供了printf函数。要使用它,您需要将-lc传递给链接器: ld -o main main.o -lc 我建议您使用C编译器作为链接器的前端,以获得可能的其他标志: cc -o main -nostartfiles main.o 请注意,由于您的程序没有初始化C标准库,它的e部分可能无法按预期工作。如果要在汇编程序中使用

我试着在没有主键的情况下编写简单的程序

汇编:

yasm -f elf64 main.s; ld -o main main.o
得到


如何解决这个问题?

C标准库
libc
提供了
printf
函数。要使用它,您需要将
-lc
传递给链接器:

ld -o main main.o -lc
我建议您使用C编译器作为链接器的前端,以获得可能的其他标志:

cc -o main -nostartfiles main.o
请注意,由于您的程序没有初始化C标准库,它的e部分可能无法按预期工作。如果要在汇编程序中使用C标准库,我建议您使汇编程序从
main
开始,并通过调用C编译器链接它:

yasm -f elf64 main.s
cc -o main main.o
你错误的原因 链接时获得printf的
未定义引用的原因是没有链接到C库。同样,当您使用自己的
\u start
标签作为入口点时,还必须克服其他问题,如下所述


在没有C运行时启动代码的情况下使用LIBC 为了确保在运行时使用适当的动态链接器,并针对C库进行链接,可以使用GCC作为LD的前端。要提供自己的
\u start
标签并避免使用C运行时启动代码,请使用
-nostartfiles
选项。虽然我不推荐这种方法,但您可以链接到:

gcc -m64 -nostartfiles main.o -o main
如果希望使用LD,可以使用特定的动态链接器,并使用
-lc
链接C库。要链接x86_64代码,可以使用:

ld -melf_x86_64 --dynamic-linker=/lib64/ld-linux-x86-64.so.2 main.o -lc -o main
如果您已经编译并链接了32位,那么链接可以通过以下方式完成:

ld -melf_i386 --dynamic-linker=/lib/ld-linux.so.2 main.o -lc -o main

使用C运行时启动代码的首选方法 <>因为你使用C库,你应该考虑链接C运行时。如果要创建静态可执行文件,此方法也可以使用。使用C库的最佳方法是将
\u start
标签重命名为
main
,然后使用GCC链接:

这样做可以让您通过从
main
返回(使用RET)退出程序,与C程序结束的方式相同。这还具有在程序退出时刷新标准输出的优点


刷新输出缓冲区/出口 使用EAX=60的
syscall
退出不会刷新输出缓冲区。因此,您可能会发现自己必须在输出上添加换行符才能在退出之前查看输出。这仍然不能保证您将看到使用
printf
输出的内容。您可以考虑调用C库函数<代码>退出>代码>而不是SysSeExthySysCurl。
退出
的手册页显示:

冲洗并关闭所有打开的stdio(3)流。由tmpfile(3)创建的文件将被删除

我建议将sys\u exit SYSCALL替换为:


因为printf是由CRT提供的,您既没有初始化也没有链接它。您链接libc了吗?没有,ld-o main.o。我认为程序在运行时会动态链接到libc。如果我错了,请纠正。是的,他们有,但是你仍然需要告诉链接器这样做。否则它怎么知道它可以在libc中找到
printf
?@MichaelPetch似乎ld默认选择了错误的解释器名称。我成功地创建了
ld-o main.o-lc
链接。然后尝试执行
/main
-失败
-bash:./main:没有这样的文件或目录
它与链接无关,但不知道问题出在哪里。它在那里:
ls-al-rwxr-x 1 name name 2832 Sep 18 15:00 main
@BulatM。非常有趣。我不确定问题是什么,让我来调查一下。@BulatM.:请参阅re:直接使用
ld
时获得正确的ELF解释器,以及更一般地说,如何从定义main或_start的源代码构建带/不带libc的静态/动态二进制文件。我真的应该重新回答这个问题,因为我写的标准答案也是对一船64位纯问题的答案,它是有效的。你能告诉我如何不用编译器只使用汇编和链接工具吗?想要了解这些基本工具是如何工作的,以获得正确的理解,而不是仅仅使用权宜之计而不理解。我编辑了答案。请您详细说明在执行
ld-o main.o
时使用了什么链接器,以及为什么bash会给出错误(非常奇怪)?@BulatM。Bash给出了一个奇怪的错误,因为在创建可执行文件时没有指定动态加载器。有趣的是,之前我认为Shell只是分叉并执行exec家族的一个函数,而不必使用加载器。
ld -melf_x86_64 --dynamic-linker=/lib64/ld-linux-x86-64.so.2 main.o -lc -o main
ld -melf_i386 --dynamic-linker=/lib/ld-linux.so.2 main.o -lc -o main
gcc -m64 main.o -o main
extern exit

xor edi, edi    ; In 64-bit code RDI is 1st argument = return value
call exit