程序结束后去哪儿了?
大家好,我是寫代碼的籃球球癡,轉發一篇卓老師的文章,文章中的內容我之前做單片機的時候也有遇到過。
推薦給大家看看~
簡 介: 對于嵌入式系統,如果沒有運行RTOS,那么程序開發中的 主函數(main())需要通過某種機制使其永遠愉快的運行下去,它沒有終點。如果想從main函數中退出,具體干什么是由所使用的C語言編譯器決定的。
關鍵詞: C51,main,程序退出
01 問題提出
??今天在CSDN的 ?單片機led模塊定義函數的問題[1] ?中看到一個有趣的問題。提問者在進行基本的C51編程實驗,編寫了一個簡單的C51程序如下:
#include?<REGX51.H>void?test(num)?{switch(num)?{case?1:?P2_0=0;?P2_1=0;?break;} }void?main(void)?{test(1); }??程序執行完之后,可以看到實驗板上的有兩個LED被點亮,另外六個居然微微發亮。
▲ 圖1.1 實驗板上的未點亮的LED居然微微發亮??如果在主程序中,增加一個無限循環:while(1); ,則電路板上的就不再會出現“微微點亮”的現象了。
#include?<REGX51.H>void?test(num)?{switch(num)?{case?1:?P2_0=0;?P2_1=0;?break;} }void?main(void)?{test(1);while(1); }▲ 圖1.2 實驗板上后面六個LED就不再點亮了??上面兩種情況的區別,在于第二個程序中 主循環 main() 函數始終沒有退出,而第一個程序,main() 函數退出了。似乎前面LED 微微點亮 應該與 主函數 退出之后,單片機都干了些啥有關系。
??那么就剩下一個問題:對于普通的嵌入式系統,C語言編程中 main()函數退出之后,程序去哪兒了?
02 程序去哪兒了?
??從上面提問者書寫的代碼來看,應該是一位C51的愛好者,使用的是C51的編譯器,在一款C51開發板上愉快的進行實驗。他一開始沒有安裝嵌入式程序開發的慣例 在主程序void main(void) 中利用無限循環將程序控制在主程序函數中,就出現了前面實驗結果中令人迷惑的情況。
注:他是一個膽大心細的人,觀察還挺仔細的。
2.1 盤古開天辟地
??對于C語言編程來說,所有的用戶程序世界是從主程序 main() ?開始的。給用戶程序開天辟地的任務是由 一小段 盤古代碼 STARTUP.A51。
??關于C51是如何啟動的, 在如下面博文中也被測試說明:
51單片機程序執行流程(STARTUP.A51管理Main函數的執行)[2]
??下面截取了 STARTUP.A51 代碼的一段,可以看到盤古在單片機 RESET 之后做了點準備工作(初始化全局變量、堆棧指針)之后,就直接跳轉至:?C_START
NAME?????C_STARTUP?C_C51STARTUP???SEGMENT???CODE ?STACK??????????SEGMENT???IDATARSEG?????STACKDS??????1EXTRN?CODE?(?C_START)PUBLIC???C_STARTUPCSEG????AT??????0 ?C_STARTUP:?????LJMP????STARTUP1RSEG?????C_C51STARTUPSTARTUP1:IF?IDATALEN?<>?0MOV?????R0,#IDATALEN?-?1CLR?????A IDATALOOP:??????MOV?????@R0,ADJNZ????R0,IDATALOOP ENDIFIF?XDATALEN?<>?0MOV?????DPTR,#XDATASTARTMOV?????R7,#LOW?(XDATALEN)IF?(LOW?(XDATALEN))?<>?0MOV?????R6,#(HIGH?(XDATALEN))?+1ELSEMOV?????R6,#HIGH?(XDATALEN)ENDIFCLR?????A XDATALOOP:??????MOVX????@DPTR,AINC?????DPTRDJNZ????R7,XDATALOOPDJNZ????R6,XDATALOOP ENDIFIF?PPAGEENABLE?<>?0MOV?????PPAGE_SFR,#PPAGE ENDIFIF?PDATALEN?<>?0MOV?????R0,#LOW?(PDATASTART)MOV?????R7,#LOW?(PDATALEN)CLR?????A PDATALOOP:??????MOVX????@R0,AINC?????R0DJNZ????R7,PDATALOOP ENDIFIF?IBPSTACK?<>?0 EXTRN?DATA?(?C_IBP)MOV??????C_IBP,#LOW?IBPSTACKTOP ENDIFIF?XBPSTACK?<>?0 EXTRN?DATA?(?C_XBP)MOV??????C_XBP,#HIGH?XBPSTACKTOPMOV??????C_XBP+1,#LOW?XBPSTACKTOP ENDIFIF?PBPSTACK?<>?0 EXTRN?DATA?(?C_PBP)MOV??????C_PBP,#LOW?PBPSTACKTOP ENDIFMOV?????SP,#?STACK-1LJMP?????C_STARTEND??上面的代碼也被博文 ?51單片機程序執行流程(STARTUP.A51)[3] 中進行逐步調試跟蹤驗證過:
▲ 圖2.1.1 ?顯示LJMP C_START 就是進入 main() 程序2.2 世界盡頭
??由于進入main() 函數是長跳轉,所以main函數是不會正常返回到啟動程序 STARTUP.A51,那么程序去哪了?
??在博文 單片機C語言while(1)的問題 中作者對于 KEIL編譯器和PIC的 MAPLAB編譯器對于main函數的最后時光進行了反匯編查看。
2.2.1 Keil編譯器
??在main函數的最后,程序增加了一下幾行代碼:
MOV?R0,?#0x7F CLR?A MOV?@R0,?A DJNZ?R0,?(3) MOV?SP,?#0x0C LJMP?main??這幾條語句,前4條,是將我們單片機的內存的前128個地址清零,第5條,是定義堆棧,第6條,是將程序重新跳轉到main函數的首行進行執行。
2.2.2 MAPLAB編譯器
??PIC 單片機語言程序進行跟蹤,發現main() 函數最后一條語句為 reset,也就是單片機直接復位,這是 MAPLAB編譯器根據 PIC 單片機特點增加的復位語句。
※ 總??結 ※
??對于嵌入式系統,如果沒有運行RTOS,那么程序開發中的 主函數(main())需要通過某種機制使其永遠愉快的運行下去,它沒有終點。
??如果想從main函數中退出,具體干什么是由所使用的C語言編譯器決定的。
參考資料
[1]
單片機led模塊定義函數的問題: https://ask.csdn.net/questions/7640604?utm_medium=distribute.pc_feed_v2.none-task-ask-ask_personrec_tag-3.pc_personrecdepth_1-utm_source=distribute.pc_feed_v2.none-task-ask-ask_personrec_tag-3.pc_personrec
[2]51單片機程序執行流程(STARTUP.A51管理Main函數的執行): https://blog.csdn.net/ChenGuiGan/article/details/88769619
[3]51單片機程序執行流程(STARTUP.A51): https://blog.csdn.net/tangsun999/article/details/45604507
總結
以上是生活随笔為你收集整理的程序结束后去哪儿了?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐几个Python+OpenCV实战项
- 下一篇: tomcat 如何进行优化?优化方案有哪