ARM64架构下通过scanf读取浮点值后打印异常的问题排查求助
问题分析与解决方案
你的问题出在scanf格式符和变量类型不匹配,以及ARM64架构下浮点类型的存储/读取规则上,咱们一步步拆解:
核心问题:scanf的格式符与变量类型不匹配
在遵循C调用约定的汇编代码中,scanf的格式符和变量类型有严格对应:
scanf("%f")用于读取4字节float类型的值,要求传入float*指针;- 你的
value定义为.double 0,是8字节的double类型,用%f去读写double变量时,只会写入前4字节,剩下的4字节保留初始值0,最终整个double变量的数值完全错误。
而printf的%f可以兼容float或double(因为float会被自动提升为double),但当你用ldr d0, [x1]读取这个被错误写入的double变量时,得到的是拼接了无效高4字节的错误值,自然打印异常。
修复方案
只需要把输入格式符改成%lf(对应8字节double类型的读取),修改你的.data段中的input_fmt:
input_fmt: .asciz "%lf"
修改后的完整代码如下:
// print_a_float_2.s .global main .extern scanf .extern printf .section .data input_str: .asciz "Input a float: " input_fmt: .asciz "%lf" // 这里改成%lf value: .double 0 output_str: .asciz "You entered %f.\n" .section .text main: // Prolog stp x29, x30, [sp, -16]! mov x29, sp // Get value from user ldr x0, =input_str bl printf ldr x0, =input_fmt ldr x1, =value bl scanf print: // Now print value ldr x0, =output_str ldr x1, =value ldr d0, [x1] bl printf // Cleanup mov x0, #0 ldp x29, x30, [sp], 16 ret
关于你调试时的疑惑解释
你提到调试时看到value中存储了正确的1.2345,但d0里的值不对——这大概率是因为调试器默认用float格式解析了value的前4字节,而实际它是一个double类型变量。当你用ldr d0, [x1]读取完整的8字节时,高4字节的0会被解析成double的指数部分,导致最终数值完全偏离预期。
内容的提问来源于stack exchange,提问作者Andrew H
相关产品推荐
相关产品推荐

