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

Linux x86_64汇编调用printf触发段错误,未修改栈也可复现

x86_64汇编调用printf段错误修复方案

问题根因

  • 栈对齐不符合ABI规范:x86_64 Linux的System V ABI要求,调用函数前栈指针rsp必须16字节对齐。进入main函数时,因上层调用main时压入了8字节返回地址,rsp对齐偏移为8;你后续先后压入rbx、rbp两个8字节寄存器,又申请了32字节栈空间,最终执行call printf前rsp对齐偏移为8,不符合要求,当printf内部用到16字节对齐的SSE指令时就会触发段错误。
  • 格式字符串定义错误:你用dd定义字符串,dd是定义4字节单元的伪指令,会自动补零填充,导致格式串存储内容不符合预期,存在潜在风险。
  • 格式符与参数不匹配:你用%i(对应32位int)打印64位寄存器rbx的值,斐波那契数超过32位范围时会出现输出错误。
  • 循环次数设置错误:rcx初始值设为1,循环只会执行1次,无法打印多个斐波那契数。

修复方法

  1. 调整栈空间申请大小,保证call printf前rsp16字节对齐,可将原来的sub rsp,32改为sub rsp,40
  2. 用db伪指令定义格式字符串,格式符改为%ld匹配64位整数
  3. 根据需要打印的数量设置rcx初始值

修正后完整代码

global  main
        extern  printf

        section .data
formatStr:
        db "%ld",0xA,0

        section .text
main:   
        push    rbx             ; 保存被调用者保护寄存器
        push    rbp             
        mov     rbp,rsp
        sub     rsp,40          ; 申请40字节栈空间,保证后续call前rsp16字节对齐

        mov     rax,0           ; A
        mov     rbx,1           ; B
        mov     rcx,20          ; 计数器,打印20个斐波那契数
fib:    
        mov     rdx,rbx         ; Temp = B
        add     rbx,rax         ; B += A
        mov     rax,rdx         ; A = 原B

        mov     QWORD[rbp-8],rax
        mov     QWORD[rbp-16],rbx
        mov     QWORD[rbp-24],rcx

        mov     rdi,formatStr
        mov     rsi,rbx
        xor     rax,rax
        call    printf

        mov     rax,QWORD[rbp-8]
        mov     rbx,QWORD[rbp-16]
        mov     rcx,QWORD[rbp-24]

        dec     rcx
        jnz     fib

        ; 退出程序
        mov     rsp,rbp 
        pop     rbp     
        pop     rbx     
        ret

编译运行命令不变

nasm -felf64 fib.asm && gcc -no-pie fib.o && ./a.out

内容的提问来源于stack exchange,提问作者Yukera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:36:03