Ubuntu下Intel x64汇编调用printf出现段错误求助
x64汇编printf调用段错误的解决方案
问题描述
编写Intel x64架构汇编程序,在Ubuntu系统中通过nasm编译、gcc链接后运行出现段错误,经排查问题出在printf函数调用处,预期输出指定消息失败,GDB调试未获取有效线索。相关代码及Makefile如下:
原汇编代码(hello3.asm)
;hello3.asm ;27/06/2024 extern printf section .data msg db "this is a message", 0 fmtstr db "%s", 0 section .bss section .text global main main: mov rdi, fmtstr mov rsi, msg mov rax, 0 call printf mov rax, 60 mov rdi, 0 syscall
原Makefile内容
hello3:hello3.o gcc -o hello3 hello3.o --no-pie -no-pie hello3.o:hello3.asm nasm -f elf64 -o hello3.o -l hello3.lst -g -F dwarf hello3.asm
问题原因
- 栈对齐不符合ABI要求:x86-64 System V ABI规定,调用函数前栈指针
rsp必须保持16字节对齐。main被调用时,栈上已压入8字节的返回地址,此时rsp未对齐,直接调用printf会触发段错误。 - 直接使用系统调用退出未清理C库环境:
printf属于C标准库函数,调用后直接用syscall执行退出操作,会跳过C库的运行时清理流程,引发未定义行为。
修复方案
修改汇编代码,调整栈对齐并改用C标准库的exit函数退出:
;hello3.asm ;27/06/2024 extern printf extern exit section .data msg db "this is a message", 0 fmtstr db "%s", 0 section .bss section .text global main main: sub rsp, 8 ; 调整栈指针至16字节对齐 mov rdi, fmtstr mov rsi, msg mov rax, 0 call printf add rsp, 8 ; 恢复栈指针 mov rdi, 0 ; 设置退出码为0 call exit ; 调用C库exit函数完成清理并退出
验证步骤
执行以下命令重新编译运行:
make clean make ./hello3
程序将正常输出this is a message,无段错误。
内容的提问来源于stack exchange,提问作者adam naanaa
相关产品推荐
相关产品推荐

