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
关键修改说明
- 调整参数顺序:将
rsi设为计数器r8(对应格式串的第一个%3d),rdx设为当前斐波那契数r9(对应第二个%30d),确保参数与格式符一一对应。 - 把
mov al, 0移到循环内部:每次调用printf前都重置al,避免printf修改rax后导致后续调用的参数信息错误。 - 格式串中的
\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
相关产品推荐
相关产品推荐

