c - STM32F4 不压入/弹出浮点寄存器

标签 c assembly arm keil compiler-bug

我有密码

const float previousTemperature = getTemperature();
someNestedFunction();
someOtherActions();
setTemperature(previousTemperature);

我的问题是 someNestedFunction(); previousTemperature 被修改了。我查看了反汇编,但找不到任何指令可以在调用之前推送或弹出存储 previousTemperature 的寄存器。

我检查了 ARM documentation它指出:

The other registers in the FPU, that is, S0-S15 and FPSCR, are always saved automatically.

我的变量存储在 S18 中,那么如何确保它能正确保存和恢复?我想找到一个可以避免与 Asm 混淆的解决方案。

我的处理器是 STM32F437ZGT,我使用 Keil uVision 5 编译器。

编辑:

到目前为止,我已经尝试对 someNestedFunction() 的内容进行注释,以找出究竟是什么修改了我的变量所在的寄存器。事实证明,它被调用

snprintf(msg, 10, "%4.2f", value/100.0f);

明天我会检查是否有任何东西破坏了堆栈。

编辑2:

previousTemperature 所在的寄存器毕竟被压入/弹出。我没有注意到,因为在 dissasebly 中使用了 D9 寄存器,它隐藏了 S18 和 S19。此外,snprintf(msg, 10, "%4.2f", value/100.0f); 中的 value 似乎是一些未初始化的垃圾。更正后,previousTemperature 始终保持不变。然而,为什么会发生这种情况对我来说是个谜,恐怕真正的问题仍然存在,我只是无法观察到任何症状。

最佳答案

很好的侦探工作,发现 reg 被保存为 D9。

你在说 snprintf 中的哪种未初始化垃圾?你传递了一个虚假的指针吗?如果是这样,那么 snprintf 可能会覆盖您的变量在堆栈中保存/恢复的位置,因为它收到的 buf 指针告诉它这样做。

堆栈上的损坏数据通常会导致错误的返回地址(导致段错误)或变量中的错误数据,这些数据本应在函数调用后继续存在。


更新:如果只是未初始化的 float ,那什么也解释不了。

建议:在最外层保存和恢复D9的地方设置断点。在保存它的堆栈地址上设置一个观察点,这样您就可以检测到内存何时被覆盖,同时它仍然保存着变量的保存值。

关于c - STM32F4 不压入/弹出浮点寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39251479/

相关文章:

assembly - 如何使用循环绘制正方形(int 10h)?

c - ARM ITE指令在这种情况下有什么用吗

c++ - 在非操作系统 Arm 板上使用 'fopen'

assembly - 比较汇编中的整数值

c - 如何使用 sscanf 从相似的行中读取特定数字?

c - 自由二维数组

c - 使用 OpenSSL 生成 RSA key 的段错误

c - 局部变量从堆栈基址指针偏移

assembly - ARM指令集中的缩写(Rn, Rd, ...)是什么意思?

c++ - 从 C 程序调用 C++ 函数