【发布时间】:2016-08-31 13:47:58
【问题描述】:
我有密码
const float previousTemperature = getTemperature();
someNestedFunction();
someOtherActions();
setTemperature(previousTemperature);
我的问题是 someNestedFunction(); previousTemperature 被修改了。我查看了反汇编,在调用之前找不到任何可以推送或弹出存储previousTemperature 的寄存器的指令。
我检查了 ARM documentation 并指出:
FPU 中的其他寄存器,即 S0-S15 和 FPSCR,总是 自动保存。
我的变量存储在 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 始终保持不变。但是,为什么会发生这种情况对我来说是个谜,我担心真正的问题仍然存在,我只是无法观察到任何症状。
【问题讨论】:
-
previosTemperature与常量的变量名不同:注意错字:(previos vs. previous)。不过,我认为这只是将代码复制到问题中的错误。如果您没有使用任何内联汇编,那么这听起来像是一个编译器错误,除非您以某种方式对编译器撒谎。 -
@PeterCordes 是的,这是一个错字。我不在任何地方使用内联汇编。
-
如果它需要在函数调用中幸存下来,编译器应该把它放在一个 ABI 说是调用保留的寄存器中。我没有使用过 Keil 工具,但是为了让普通的 C 语义(比如变量保持其值!)正常工作,必须做任何特殊的事情是不正常的。
-
您确定变量保存在寄存器中吗?它不能保存在堆栈中吗?在这种情况下,您可能有一个错误会破坏
someNestedFunction中的堆栈。尝试评论它的一部分,直到你将问题缩小到罪魁祸首(这当然假设注释掉对someNestedFunction的调用首先“解决”了问题) -
根据the ABI,s16-s31 是被调用者保存的,因此其中一个中间函数(或可能是中断处理程序)要么破坏堆栈,要么在编译器背后触摸 FP 寄存器。你想调试和修复那个,而不是在这个函数中绕开它。此外,在异常条目上调用者保存的寄存器的自动堆叠,也就是你所提到的,实际上与这里没有任何关系。
标签: c assembly arm keil compiler-bug