NASM x86-64中使用scanf读取浮点数失败问题排查
x86-64汇编中scanf读取浮点数后值未更新的问题解决
你用x86-64汇编实现读取浮点数并打印,但scanf的缓冲区变量price始终保持初始的0.0,编译命令为:
nasm -f elf64 test.asm && gcc -no-pie test.o -o test
对应代码如下:
section .data price dq 0.0 fmt db "%.1f", 0 section .text global main extern printf, scanf main: push rbp mov rbp, rsp mov rdi, fmt ;scanf first arg, format string mov rsi, price ;scanf second argument, this variable is supposed to change mov rax, 0 call scanf movq xmm0, [price] ;in float point mode xmm0 holds the value to be printed mov rdi, fmt mov rax, 1 ;rax has to be set 1 to float point mode call printf leave ret
错误原因与解决方法
问题核心是格式字符串与变量类型不匹配:
- C标准库中,
scanf的%f格式符仅对应float*类型,用于读取4字节的float;而你的price是用dq定义的8字节变量,对应C中的double类型,读取double必须使用%lf格式符。 - 而
printf的%f可以兼容double(float会被自动提升为double),所以printf部分的格式符本身没问题。
修改方案1:使用独立的格式字符串(更清晰)
分别定义scanf和printf的格式字符串,避免混淆:
section .data price dq 0.0 scanf_fmt db "%lf", 0 ; 用于scanf读取double类型 printf_fmt db "%.1f", 0 ; 用于printf格式化输出double section .text global main extern printf, scanf main: push rbp mov rbp, rsp ; 调用scanf读取浮点数 mov rdi, scanf_fmt mov rsi, price mov rax, 0 call scanf ; 调用printf打印浮点数 movq xmm0, [price] mov rdi, printf_fmt mov rax, 1 call printf leave ret
修改方案2:共用兼容格式字符串
printf同样支持%lf格式符输出double,因此可以直接把格式字符串改为"%lf",同时适配scanf和printf:
section .data price dq 0.0 fmt db "%lf", 0 section .text global main extern printf, scanf main: push rbp mov rbp, rsp mov rdi, fmt mov rsi, price mov rax, 0 call scanf movq xmm0, [price] mov rdi, fmt mov rax, 1 call printf leave ret
额外说明:你传入rsi的price是正确的——nasm中变量名直接代表该变量的内存地址,符合scanf需要指针参数的要求。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

