avr-gcc程序中的main()函數將寄存器狀態保存在堆棧中,但是當運行時調用它時,我明白在單片機上沒有任何可返回的東西。這是浪費RAM嗎?如何防止這種狀態儲蓄?爲什麼在調用main()時,avr-gcc會不自覺地保存寄存器狀態?
回答
最有可能的主要是編寫在同一個標準函數。在C中,它非常需要,因爲你可以從某個地方調用它。
請注意,在C++中,遞歸調用main是非法的,因此C++編譯器可能會更好地優化它。但在C中,因爲你的問題指出,遞歸調用main是合法的(如果一個壞主意),所以它需要以與其他函數相同的方式進行編譯。
這都是關於C標準的。
什麼都不能阻止你在某個時候退出主界面。你可能不會在你的程序中做到這一點,但其他人可能會這樣做。
此外,您可以通過atexit
運行時功能註冊清理處理程序。這些函數需要一個定義好的寄存器狀態才能正確執行,唯一的方法就是保存和恢復主寄存器。
它甚至可能是有用的這樣做: 我不知道AVR,但其他微控制器可以進入低功耗狀態,當他們完成他們的工作,並等待重置。從清除處理程序執行此操作可能是一個好主意,因爲如果您以正常方式退出主程序和(就我而言),如果程序通過終止信號被中斷,則會調用此處理程序。
編譯器如何確定你不會遞歸調用main()?
如何防止這種狀態的保存?
你唯一能做的就是寫你自己的C-Startup例程。這意味着與彙編程序混淆,但您可以跳至main()而不是僅調用它。
在我用avr-gcc 4.3.5進行的測試中,如果不是優化太多,它只會保存寄存器。正常級別(-Os或-O2)會導致推送指令被優化。 可以在函數聲明中進一步指定它不會以__attribute__((noreturn))
返回。使用-fwhole程序進行全面的程序優化也很有用。
avr-libc中的初始代碼確實使用call來跳轉到main,因爲它指定主可能會返回,然後跳轉到退出(它被聲明爲noreturn並因此不生成任何調用)。如果你覺得太多,你可以鏈接你自己的變體。退出()只是簡單地禁用中斷並進入一個無限循環,有效地停止你的程序,但不會節省任何電力。如果main()永遠不會返回或調用exit(),那麼這是四條指令和兩個字節的堆棧內存開銷。
- 1. 函數調用後寄存器的狀態是什麼?
- 2. 爲什麼MOVWF不影響狀態寄存器?
- 3. 使用mksession保存vim狀態不會保存Ctrl-6狀態
- 4. 爲什麼setjmp(3)不保存AMD64上的所有寄存器?
- 5. gcc爲什麼在讀取時保存一個被調用者保存寄存器?
- 6. 爲什麼選中狀態不會被保存?
- 7. 爲什麼卡門鐵路不會違約保存的狀態?
- 8. TextView(帶ID)爲什麼不自動保存它的狀態?
- 9. 爲什麼使用臨時寄存器將值傳遞給段寄存器?
- 10. 寄存器和臨時寄存器有什麼區別?
- 11. 什麼是被調用者和調用者保存的寄存器?
- 12. 跳轉後寄存器和變量未保存狀態
- 13. 爲什麼值被存儲在寄存器0x605040c,而不是12?
- 14. INVOKE MASM自動保存寄存器?
- 15. 確實gcc保存被調用者保存寄存器
- 16. 爲什麼存儲在寄存器中的數據有內存地址?
- 17. AVR [爲什麼IO寄存器具有IO地址和SRAM不會忽略]
- 18. 未保存會話狀態
- 19. 爲什麼編譯器將變量存儲在寄存器中?
- 20. 保存地圖狀態
- 21. MIPS寄存器保存
- 22. ARM程序狀態寄存器
- 23. Z80狀態標誌寄存器
- 24. 啓動後的寄存器狀態
- 25. 爲什麼24位寄存器?
- 26. 爲什麼只有四個寄存器?
- 27. 爲什麼我的Virtual Server 2005虛擬機會自動保存狀態?
- 28. 什麼函數保存樹的狀態?
- 29. 爲什麼在調用main()時出錯?
- 30. GCC不在函數調用中保存/恢復保留的寄存器
這可能是特定於您的avr-gcc版本。我無法用4.5.1來觀察這一點。唯一的浪費是'main()'實際上被調用,因此返回地址將無用地躺在棧上,通常情況下main()不返回。 – ndim 2011-04-14 00:09:41