C 从气体组件链接和调用printf
我遇到了一些与此相关的问题,比如和,但我希望这有点不同 我有以下计划:C 从气体组件链接和调用printf,c,assembly,x86,x86-64,system-calls,C,Assembly,X86,X86 64,System Calls,我遇到了一些与此相关的问题,比如和,但我希望这有点不同 我有以下计划: .section .data format: .ascii "%d\n" .section .text .globl _start _start: // print "55" mov $format, %rdi mov $55, %rsi mov $0, %eax call printf # how to link?
.section .data
format:
.ascii "%d\n"
.section .text
.globl _start
_start:
// print "55"
mov $format, %rdi
mov $55, %rsi
mov $0, %eax
call printf # how to link?
// exit
mov $60, %eax
mov $0, %rdi
syscall
与此相关的两个问题:
- 是否可以仅使用
(气体)和as
将其链接到ld
功能,使用printf
作为入口点?如果是的话,那怎么办呢\u start
- 如果不是,除了将
更改为\u start
,正确运行的main
调用是什么gcc
ld
,但不推荐使用:如果使用libc函数,则需要初始化C运行时。如果您让C编译器提供\u start
并以main
的身份启动程序,那么这将自动完成。如果您使用的是libc而不是C运行时初始化代码,那么它似乎可以工作,但也可能导致奇怪的错误
如果您从main
(第二种情况)启动程序,则只需执行gcc-o program.s
,其中program.s
是您的源文件。在某些Linux发行版上,您可能还需要提供-no pie
,因为您的程序不是用PIC风格编写的(暂时不要担心这个问题)
还要注意,我建议不要将libc调用与原始系统调用混合使用。不要执行原始退出系统调用,而是调用C库函数exit
。这可以让C运行时正确地去初始化自己,包括刷新任何IO流
现在,如果你像我在第一段中说的那样组装并链接你的程序,你会注意到它可能会崩溃。这是因为调用函数时堆栈需要与16字节的倍数对齐。您可以通过在每个函数开始时在堆栈上按一个数据字来确保这种对齐(记住在末尾将其弹出)。可以使用
ld
,但不推荐使用:如果使用libc函数,则需要初始化C运行时。如果您让C编译器提供\u start
并以main
的身份启动程序,那么这将自动完成。如果您使用的是libc而不是C运行时初始化代码,那么它似乎可以工作,但也可能导致奇怪的错误
如果您从main
(第二种情况)启动程序,则只需执行gcc-o program.s
,其中program.s
是您的源文件。在某些Linux发行版上,您可能还需要提供-no pie
,因为您的程序不是用PIC风格编写的(暂时不要担心这个问题)
还要注意,我建议不要将libc调用与原始系统调用混合使用。不要执行原始退出系统调用,而是调用C库函数exit
。这可以让C运行时正确地去初始化自己,包括刷新任何IO流
现在,如果你像我在第一段中说的那样组装并链接你的程序,你会注意到它可能会崩溃。这是因为调用函数时堆栈需要与16字节的倍数对齐。您可以通过在每个函数的开头在堆栈上按一个数据字来确保对齐(请记住在末尾将其弹出)。您的问题与我们以前多次看到的问题完全相同。尽管如此,我还是给你写了一个答案。我希望它能帮助你。对于将来的问题,一定要写下你尝试过的,以及为什么你尝试过的不适合你。这会让其他人更好地理解你的处境。@NateEldredge不,但那是完美的,谢谢你的链接!这回答了你的问题吗?你的问题和我们以前在这里见过很多次的完全一样。尽管如此,我还是给你写了一个答案。我希望它能帮助你。对于将来的问题,一定要写下你尝试过的,以及为什么你尝试过的不适合你。这会让其他人更好地理解你的处境。@NateEldredge不,但那是完美的,谢谢你的链接!这回答了你的问题吗?谢谢,关于
,请注意,我建议不要将libc调用与原始系统调用混合使用。不要执行原始退出系统调用,而是调用C库函数exit
。如果我在最后做了ret
,会有效果吗?@carl.hiass:不会的。您可以在图3.9中读取程序入口的堆栈上的内容。注意,那里没有回信地址;堆栈的底部包含参数计数。如果您尝试ret
您将跳转到地址1或地址2或其他任何位置,然后执行segfault.@NateEldredge当通过gcc调用时,它对我有效。让我发布另一个与此相关的问题…@NateEldredge如果使用main
而不是\u start
,您当然可以返回。我明白了,我不清楚我们讨论的是哪种情况。您不能从\u start
执行ret
,但可以从main
执行。谢谢,关于请注意,我建议不要将libc调用与原始系统调用混合使用。不要执行原始退出系统调用,而是调用C库函数exit
。如果我在最后做了ret
,会有效果吗?@carl.hiass:不会的。您可以在图3.9中读取程序入口的堆栈上的内容。注意,那里没有回信地址;堆栈的底部包含参数计数。如果您尝试ret
您将跳转到地址1或地址2或其他任何位置,然后执行segfault.@NateEldredge当通过gcc调用时,它对我有效。让我发布另一个与此相关的问题…@NateEldredge如果使用main
而不是\u start
,您当然可以返回。我明白了,我不清楚我们讨论的是哪种情况。您不能从\u start
执行ret
,但可以从main
执行。