问题记录:交换两行printf -打印结果不同

40 篇文章 10 订阅
14 篇文章 0 订阅

环境

os: windows
IDE: iar
toolchain:iar9.32
board: STM32F429

问题描述

同一个float变量,用两行printf打印,先%d打出来,再%.3f打出来,前者输出32(正确),后者打出来是0.000。顺序调换后 .3f也正常了

先打印int,再打印float,输出是32和0.000
在这里插入图片描述

先打印float,再打印int,输出是32.123和32 (正确输出)
在这里插入图片描述

问题定位

vcvtq_s32_f32 Qd, Qm, 浮点数 ----> 有符号整数或者定点数
printf用%d格式打印val,会使用vcvtq_s32_f32 指令做一次转换。
在这里插入图片描述
b1c4地址上的VLDR用于将处于栈顶的val值,放入S0浮点寄存器中
(S0 ~ S31(S)都为32位寄存器,可通过浮点指令或利用符号D0 ~ D15(D代表双字/双精度)成对访问。 例如,S0和S1成对组成D0,而S2和S3则成对组成D1。)

b1c8地址上将字符串地址传入R0

b1ca地址上的VCVT.S32.F32,就是对S0进行浮点数 ----> 有符号整数的转换了,从左到右第一个S0是目的寄存器,这行结束后S0值为32(较大的精度丢失,向零舍入,即将浮点数的小数部分去除,以获取整数部分)

b1ce上的VMOV将S0里的32存入R1,可视作整数存储。

b1d2调用printf

再打印float
红框里的mov没有效果,根据函数调用约定,传入printf的值依然是R0和R1(r0来自[SP],即val,给的R2,但传入printf依然是R0,R1。R1的值依然是b1ce上VMOV后的结果32,用格式%f去输出32,最后输出值为0.000
在这里插入图片描述
在X86机器上做了实验,行为也是一样的:
测试代码:
在这里插入图片描述
结果:
在这里插入图片描述

到这儿,也就很容易看出为什么交换这俩printf的顺序,结果又正确了。

随后我们做了两个尝试:

  1. 关闭FPU,因为编译出的代码没有使用VCVT做转换,所以结果正确(无论是否交换顺序)
  2. include stdio.h后,结果也正确(无论是否交换顺序),从而引出了另一个问题

另一个问题

include stdio.h后,不交换printf顺序,输出也正常了,再次看汇编,发现这次printf传参时的参数准备行为变得正常了:
在这里插入图片描述
通过VMOV将R0, R1的值传入D0(双精度, 因为格式化打印用的是.3f 会做精度提升到double),r0和r1的值应该是经过__aeabi_f2d之后的返回值(在实际编程中,VFP 中的浮点运算实际是组合使用硬件(执行常见的情况)和软件(处理不常见的情况和导致异常的情况)执行的。__aeabi_f2d即为软件浮点库中的实现)

这里的printf的入参为R0, D0?这里得保持疑问。 TODO:
另外,第二个问题,为什么include stdio后,编译器对printf传参行为也变了。TODO:

参考资料:

  1. https://www.cnblogs.com/YYPapa/p/6854371.html
  2. https://blog.csdn.net/sno_guo/article/details/8472809
  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值