NASM elf64汇编调用C函数传参时触发SIGFPE错误
问题根因
你遇到的SIGFPE(除零错误)本质是64位汇编调用C函数时违反了平台调用约定,具体问题点如下:
- 传参方式完全错误:x86_64 Linux ELF遵循System V AMD64调用约定,C函数的前6个整数参数不通过栈传递,而是依次存入
rdi、rsi、rdx、rcx、r8、r9寄存器。你把参数9压栈的操作不会被le_sqrt识别,函数读取参数a时会直接取edi寄存器里的随机残留值,一旦这个值为0,执行number/n的除法指令时就会触发除零异常,抛出SIGFPE。这也是你把a直接写在函数内部时程序能正常运行的原因——此时不需要从外部寄存器读参数,不会拿到垃圾值。 - exit系统调用参数寄存器用错:64位Linux的60号
exit系统调用,退出码参数需要放在rdi寄存器,你写的mov rsi,0是无效的,会导致进程退出码不符合预期。 - 栈对齐不符合要求:64位环境下调用C函数前,栈指针
rsp必须保持16字节对齐。程序进入_start入口时栈天然是16字节对齐的,你额外push一个8字节的rbp后栈就变成8字节错位,再执行call指令压入8字节返回地址,进入le_sqrt时栈就不符合对齐要求,可能触发其他隐性崩溃。
修正后的汇编代码
bits 64 global _start extern le_sqrt _start: mov rdi, 9 ; 第一个int参数按约定存入rdi,不需要压栈 call le_sqrt ; 调用C函数,返回值默认存在rax中 mov rax, 60 ; exit系统调用号 mov rdi, 0 ; 退出码存入rdi,如果要使用sqrt计算结果作为退出码,改成mov rdi, rax即可 syscall
内容的提问来源于stack exchange,提问作者BerretMan
相关产品推荐
相关产品推荐

