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

X64汇编调用printf出现乱码/段错误问题求助

x86-64汇编调用printf出现乱码/段错误的解决方法

问题根源

你的代码存在两个核心问题:

  • 参数顺序完全错误:格式字符串"%3d: %30d\n"需要两个整数参数,第一个是计数器(对应%3d),第二个是当前斐波那契数(对应%30d),但你现在传递的是rsi=r9(斐波那契数)、rdx=r10(下一个斐波那契数),完全不匹配格式符,这是乱码的直接原因。
  • al寄存器的设置时机错误:在x86-64 System V调用约定中,可变参数函数(如printf)需要通过al寄存器告知函数有多少个浮点参数存储在XMM寄存器中。你的代码没有使用浮点参数,所以必须将al设为0。但printf会修改rax寄存器的值,因此每次调用printf前都需要重新设置al=0——只在循环外设置一次的话,后续调用时al的值已经被破坏,会导致printf行为异常(比如段错误)。

修正后的代码

;print all fib numbers from 0 until 100
global main
extern printf
;printf notes
;mov al, 0 is necessary (no floating-point args)
;rdi: format string
;rsi, rdx, r8... args (in order of format specifiers)
section .text
main:
    mov r8, 0          ;counter
    mov r9, 0          ;current fib value (nth)
    mov r10, 1         ;next fib value (n+1th)

Loop:
    ; Set up printf arguments in correct order
    mov rdi, format_str ; 1st arg: format string
    mov rsi, r8         ; 2nd arg: counter (matches %3d)
    mov rdx, r9         ; 3rd arg: current fib number (matches %30d)
    mov al, 0           ; Must set al=0 before each printf call (no XMM args)
    call printf

    ; Update fib sequence
    mov r11, r10
    add r10, r9
    mov r9, r11
    inc r8
    cmp r8, 100
    jl Loop

    ; Exit program
    mov rax, 60
    mov rdi, 0
    syscall

section .rodata
format_str: db "%3d: %30d", 10, 0 ; Using 10 instead of \n is equivalent in asm

关键修改说明

  1. 调整参数顺序:将rsi设为计数器r8(对应格式串的第一个%3d),rdx设为当前斐波那契数r9(对应第二个%30d),确保参数与格式符一一对应。
  2. 把mov al, 0移到循环内部:每次调用printf前都重置al,避免printf修改rax后导致后续调用的参数信息错误。
  3. 格式串中的\n替换为10(ASCII换行符的数值),这在汇编中是更直接的写法,效果完全一致。

编译运行方法:

nasm -f elf64 your_file.asm -o your_file.o
gcc your_file.o -o your_program
./your_program

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 16:40:19