簡 介:對于嵌入式系統,如果沒有運行RTOS,那么程序開發中的 主函數(main())需要通過某種機制使其永遠愉快的運行下去,它沒有終點。如果想從main函數中退出,具體干什么是由所使用的C語言編譯器決定的。
01問題提出
今天在CSDN的 單片機led模塊定義函數的問題[1]中看到一個有趣的問題。提問者在進行基本的C51編程實驗,編寫了一個簡單的C51程序如下:
#include
程序執行完之后,可以看到實驗板上的有兩個LED被點亮,另外六個居然微微發亮。
▲ 圖1.1 實驗板上的未點亮的LED居然微微發亮
如果在主程序中,增加一個無限循環:while(1);,則電路板上的就不再會出現“微微點亮”的現象了。
#include
▲ 圖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_C51STARTUPSEGMENTCODE ?STACKSEGMENTIDATA RSEG?STACK DS1 EXTRNCODE(?C_START) PUBLIC?C_STARTUP CSEGAT0 ?C_STARTUP:LJMPSTARTUP1 RSEG?C_C51STARTUP STARTUP1: IFIDATALEN<>0 MOVR0,#IDATALEN-1 CLRA IDATALOOP:MOV@R0,A DJNZR0,IDATALOOP ENDIF IFXDATALEN<>0 MOVDPTR,#XDATASTART MOVR7,#LOW(XDATALEN) IF(LOW(XDATALEN))<>0 MOVR6,#(HIGH(XDATALEN))+1 ELSE MOVR6,#HIGH(XDATALEN) ENDIF CLRA XDATALOOP:MOVX@DPTR,A INCDPTR DJNZR7,XDATALOOP DJNZR6,XDATALOOP ENDIF IFPPAGEENABLE<>0 MOVPPAGE_SFR,#PPAGE ENDIF IFPDATALEN<>0 MOVR0,#LOW(PDATASTART) MOVR7,#LOW(PDATALEN) CLRA PDATALOOP:MOVX@R0,A INCR0 DJNZR7,PDATALOOP ENDIF IFIBPSTACK<>0 EXTRNDATA(?C_IBP) MOV?C_IBP,#LOWIBPSTACKTOP ENDIF IFXBPSTACK<>0 EXTRNDATA(?C_XBP) MOV?C_XBP,#HIGHXBPSTACKTOP MOV?C_XBP+1,#LOWXBPSTACKTOP ENDIF IFPBPSTACK<>0 EXTRNDATA(?C_PBP) MOV?C_PBP,#LOWPBPSTACKTOP ENDIF MOVSP,#?STACK-1 LJMP?C_START END
上面的代碼也被博文 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函數的最后,程序增加了一下幾行代碼:
MOVR0,#0x7F CLRA MOV@R0,A DJNZR0,(3) MOVSP,#0x0C LJMPmain
這幾條語句,前4條,是將我們單片機的內存的前128個地址清零,第5條,是定義堆棧,第6條,是將程序重新跳轉到main函數的首行進行執行。
2.2.2 MAPLAB編譯器
PIC 單片機語言程序進行跟蹤,發現main() 函數最后一條語句為reset,也就是單片機直接復位,這是 MAPLAB編譯器根據 PIC 單片機特點增加的復位語句。
※總??結 ※
對于嵌入式系統,如果沒有運行RTOS,那么程序開發中的 主函數(main())需要通過某種機制使其永遠愉快的運行下去,它沒有終點。
如果想從main函數中退出,具體干什么是由所使用的C語言編譯器決定的。
審核編輯 :李倩
-
嵌入式系統
+關注
關注
41文章
3625瀏覽量
129757 -
C51
+關注
關注
5文章
283瀏覽量
58285
原文標題:程序結束后去哪兒了?
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論