Linux x86_64下如何链接NASM程序以获取argc?
为什么
_start直接返回0,main却能返回参数个数? 核心差异在于启动流程
用ld直接链接_start的情况
Linux x86_64内核启动程序时,确实会把参数个数argc放到rdi寄存器里,然后跳转到_start入口。但你的代码返回0,要么是测试时的误解(比如直接运行./a.out时argc=1,你可能误判为0),要么是链接时的隐性问题——不过更关键的是:直接用ld链接时没有C运行时(CRT)的辅助,所有寄存器状态完全依赖内核的初始传递,没有任何额外的参数整理逻辑。如果你的代码没动rdi,理论上应该返回argc,但如果实际返回0,建议用gdb调试看_start处的rdi值。
用gcc链接main的情况
gcc会自动帮你链接CRT启动代码(比如crt0.o),这些代码会帮你做这些事:
- 初始化栈、全局变量
- 从内核传递的寄存器里取出
argc和argv - 按照x86_64函数调用约定,把
argc放进rdi,argv放进rsi,然后调用main - 等
main返回后,再调用exit系统调用传递返回值
所以你的main代码直接调用sys_exit时,rdi里正好是argc,自然能返回参数个数。
值得参考的文档
- Linux内核源码里的
Documentation/x86/entry.rst:讲x86_64进程启动时的寄存器状态和入口逻辑 - NASM官方文档:学习x86_64汇编语法、编译和链接规则
- GNU ld手册:了解链接脚本、入口点设置和默认启动代码的细节
man 2 syscall:查询x86_64系统调用的参数传递规则和调用号
内容的提问来源于stack exchange,提问作者Hymns For Disco
相关产品推荐
相关产品推荐

