为什么avr-gcc在调用main()时会费心保存寄存器状态?

时间:2010-07-14 20:26:31

标签: c stack microcontroller avr avr-gcc

avr-gcc程序中的main()函数将寄存器状态保存在堆栈中,但是当运行时调用它时,我理解在微控制器上没有任何东西可以返回。这是浪费RAM吗?如何防止这种状态储存?

5 个答案:

答案 0 :(得分:6)

编译器如何确保您不会递归调用main()?

答案 1 :(得分:4)

这完全是关于C标准的。

在某些时候,没有什么禁止你退出主要的。您可能不会在您的计划中执行此操作,但其他人可能会这样做。

此外,您可以通过atexit运行时函数注册清理处理程序。这些函数需要一个定义的寄存器状态才能正确执行,唯一的方法就是保存和恢复main周围的寄存器。

这样做甚至可能有用: 我不知道AVR,但是当其他微控制器完成工作并等待复位时,它们可以进入低功耗状态。从清理处理程序执行此操作可能是一个好主意,因为如果您的程序通过kill-signal中断,如果以正常方式(就我现在而言)退出main,则会调用此处理程序。

答案 2 :(得分:3)

最有可能的主要编译方式与标准函数相同。在C中,它几乎需要,因为你可以从某个地方调用它。

请注意,在C ++中,以递归方式调用main是非法的,因此c ++编译器可能能够更好地优化它。但是在C中你的问题表明,以递归方式调用main是合法的(如果是个坏主意)所以它需要以与任何其他函数相同的方式编译。

答案 3 :(得分:1)

  

如何防止这种状态储存?

您唯一能做的就是编写自己的C-Startup例程。这意味着搞乱汇编程序,但你可以JUMP到你的main()而不是只是调用它。

答案 4 :(得分:1)

在我使用avr-gcc 4.3.5进行的测试中,如果没有进行太多优化,它只会保存寄存器。正常水平(-Os或-O2)会使推送指令最优化。 可以在函数声明中进一步指定它不会返回__attribute__((noreturn))。使用-fwhole-program进行完整的程序优化也很有用。

avr-libc中的初始代码确实使用call跳转到main,因为指定main 可能返回,然后跳转到exit(声明为noreturn,因此不生成调用) 。如果您认为太多,可以链接自己的变体。 exit()依次禁用中断并进入无限循环,有效地停止程序,但不保存任何电源。如果你的main()永远不会返回或调用exit(),那就是四个指令和两个字节的堆栈内存开销。