从NASM向C传递命令行参数时触发段错误,求技术解决方案
问题分析与解决建议
核心问题根源
你遇到的段错误完全是因为违反了x86-64 Linux的System V AMD64调用约定,具体问题点:
- 参数传递方式错误:x86-64下前6个整数/指针参数是通过寄存器传递的,而非栈。
argc需要放在RDI,argv需要放在RSI,你的代码直接调用函数,函数会去寄存器找参数,自然读取到非法值导致访问错误。 - 栈对齐要求未满足:调用C函数前,栈指针
RSP必须处于16n + 8的位置(call指令会压入8字节返回地址,确保进入函数后RSP是16字节对齐,这是ABI强制要求),而_start被内核初始化时RSP是16字节对齐的,直接调用会破坏对齐规则,触发内存访问异常。 _start不是普通函数:它没有调用者,不能用ret返回,必须通过exit系统调用或函数终止程序。
修正后的汇编代码
extern func extern exit section .text _start: ; 从内核初始化的栈中读取argc和argv,放入调用约定要求的寄存器 mov rdi, [rsp] ; 第一个参数:argc -> RDI mov rsi, [rsp + 8] ; 第二个参数:argv -> RSI ; 调整栈对齐:内核启动时RSP是16字节对齐,sub rsp,8后变为16n+8,call后RSP为16n(符合函数入口对齐要求) sub rsp, 8 ; 调用C函数 call func ; 函数返回后,调用exit结束程序(_start不能用ret返回) mov rdi, 0 ; 退出码设为0 call exit
额外注意事项
- 如果你的
struct of_my_creation大小超过16字节,x86-64调用约定会要求调用者提前分配返回结构的空间,并将指针作为第一个参数传递(此时argc会变为第二个参数,对应RSI,argv对应RDX),需要根据结构体大小调整参数传递逻辑。 - 编译链接命令示例:
nasm -f elf64 your_asm.s -o your_asm.o gcc -c your_c.c -o your_c.o gcc your_asm.o your_c.o -o your_program
内容的提问来源于stack exchange,提问作者R-Rothrock
相关产品推荐
相关产品推荐

