You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修正点说明

  1. 16字节栈对齐
    64位系统中,所有外部函数调用前必须保证rsp是16字节的倍数。main函数被调用时,返回地址(8字节)已压入栈,此时rsp偏移8字节,需手动调整栈恢复对齐,否则printf内部访问栈时会触发段错误。

  2. exit函数的正确调用

    • Linux下exit的参数通过rdi传递,不能用push 0的方式,这会破坏栈对齐。
    • Windows下应使用ExitProcess而非exit,参数通过rcx传递,同时需遵守阴影空间规则。
  3. 打印内容修正
    原代码使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:30:25