x86汇编实现斐波那契循环时 scanf读入变量传值错误、打印异常排查
代码问题定位与修正方案
核心错误点
- 调用约定混淆:64位Linux下调用libc函数遵循System V AMD64 ABI,前6个整数/指针参数通过
rdi、rsi、rdx、rcx、r8、r9传递,不需要像32位cdecl那样手动压栈传参。你之前的乱序push/pop操作不仅没有正确传参,还打乱了寄存器值和栈对齐,直接导致参数传递错误。 - 地址与变量值混淆:给
scanf传递的rsi是var1的内存地址,在你当前的编译环境下这个地址换算成十进制就是4206708,你后续直接执行mov rax, rsi,把这个固定的内存地址当成了斐波那契的初始计算值,后续的所谓斐波那契计算其实是在两个相邻地址值上做累加,这也是你输出里出现4206708、4206709、8413419这类无意义大数的根本原因。 - 格式串复用错误:你定义的
format带了换行符0xa,作为scanf的格式串时,换行符会触发scanf连续跳过所有空白符的逻辑,导致输入行为异常。 - 寄存器值误用:你硬编码了循环计数器为10,没有从
var1的内存空间里读取用户实际输入的循环次数,计算全程没有用到用户输入的有效数值。
分步修正实现
1. 数据段定义调整
拆分打印、扫描需要的独立格式串,避免格式串逻辑冲突:
section .data print_fmt: db "%d", 10, 0 ; 打印整数并换行的格式 scan_fmt: db "%d", 0 ; 读取整数的专用格式,不带换行 title: db "Fib Numbers", 10, 0 asknum: db "Enter a number to get the fibonacci sequence of: ", 10, 0 section .bss var1 resd 1 ; 存储用户输入的循环次数,32位空间足够
2. 代码段流程修正
严格按照调用约定传递参数,正确读取变量值完成斐波那契循环:
_start: push rbp mov rbp,rsp sub rsp, 16 ; 保证调用libc时栈16字节对齐 ; 打印输入提示 mov rdi, asknum xor rax, rax call printf ; 读取用户输入 mov rdi, scan_fmt mov rsi, var1 ; 传递var1的内存地址给scanf xor rax, rax call scanf ; 打印序列标题 mov rdi, title xor rax,rax call printf ; 初始化计算参数 mov rcx, [var1] ; 从var1的内存地址读取用户输入的循环次数 mov rax, 0 ; 斐波那契初始值a=0 mov rbx, 1 ; 斐波那契初始值b=1 .fib_loop: ; 打印当前的斐波那契数 mov rdi, print_fmt mov rsi, rax xor rax, rax call printf ; 迭代计算下一个数:temp = a + b; a = b; b = temp mov rdx, rax add rax, rbx mov rbx, rdx dec rcx jnz .fib_loop ; 退出程序 mov rax, 60 xor rdi, rdi syscall
修正后的运行效果
程序会按照用户输入的次数,依次输出0、1、1、2、3、5……的标准斐波那契序列,不会再出现内存地址类的异常大数。
内容的提问来源于stack exchange,提问作者AerialSong
相关产品推荐
相关产品推荐

