64位NASM汇编调用C printf打印数字触发段错误求助
解决64位汇编中printf触发段错误的问题
问题根源
你的代码触发段错误的核心原因是栈未满足64位调用约定的16字节对齐要求,同时exit的调用方式不符合64位系统规范。
修正后的代码
Linux/Ubuntu(System V AMD64调用约定)
section .data num dq 6 ; 替换原radius,改为要打印的数字6 pi dq 3.1416 fmt db "Hello %d", 10, 0 section .text global main extern printf extern exit main: mov rbp, rsp ; 调试用,不影响对齐,但后续需手动调整栈 sub rsp, 8 ; main被调用时rsp因返回地址偏移8字节,减8后恢复16字节对齐 mov rdi, fmt ; 第一个参数:格式字符串地址 mov rsi, [num] ; 第二个参数:要打印的数字6 call printf mov rdi, 0 ; exit的退出码参数通过rdi传递 call exit
Windows(Win64调用约定)
Win64下需注意前4个参数用rcx/rdx/r8/r9传递,且要预留32字节的“阴影空间”:
section .data num dq 6 pi dq 3.1416 fmt db "Hello %d", 10, 0 section .text global main extern printf extern ExitProcess main: mov rbp, rsp sub rsp, 40 ; 32字节阴影空间 + 8字节对齐,确保调用前rsp为16字节倍数 mov rcx, fmt ; 第一个参数用rcx传递 mov rdx, [num] ; 第二个参数用rdx传递 call printf mov rcx, 0 ; ExitProcess的退出码参数用rcx传递 call ExitProcess
关键修正点说明
16字节栈对齐
64位系统中,所有外部函数调用前必须保证rsp是16字节的倍数。main函数被调用时,返回地址(8字节)已压入栈,此时rsp偏移8字节,需手动调整栈恢复对齐,否则printf内部访问栈时会触发段错误。exit函数的正确调用
- Linux下
exit的参数通过rdi传递,不能用push 0的方式,这会破坏栈对齐。 - Windows下应使用
ExitProcess而非exit,参数通过rcx传递,同时需遵守阴影空间规则。
- Linux下
打印内容修正
原代码使用radius dq 10会打印10而非期望的6,因此改为num dq 6。
编译运行命令
Linux/Ubuntu
nasm -f elf64 -o output.o input.asm gcc -o program output.o ./program
Windows
nasm -f win64 -o output.obj input.asm gcc -o program.exe output.obj program.exe
内容的提问来源于stack exchange,提问作者Margorp13
相关产品推荐
相关产品推荐

