正常的程序,都不會(huì)跳出main,但是,如果跳出了 main 函數(shù),程序到底去哪兒了,你有相關(guān)這個(gè)問(wèn)題嗎?
一、問(wèn)題提出
今天在單片機(jī)led模塊定義函數(shù)中看到一個(gè)有趣的問(wèn)題。提問(wèn)者在進(jìn)行基本的C51編程實(shí)驗(yàn),編寫了一個(gè)簡(jiǎn)單的C51程序如下:
#include void test(num) { switch(num) { case 1: P2_0=0; P2_1=0; break; } } void main(void) { test(1); }
程序執(zhí)行完之后,可以看到實(shí)驗(yàn)板上的有兩個(gè)LED被點(diǎn)亮,另外六個(gè)居然微微發(fā)亮。

如果在主程序中,增加一個(gè)無(wú)限循環(huán):while(1); ,則電路板上的就不再會(huì)出現(xiàn)“微微點(diǎn)亮”的現(xiàn)象了。
#include
void test(num) {
switch(num) {
case 1: P2_0=0; P2_1=0;
break;
}
}
void main(void) {
test(1);
while(1);
}

上面兩種情況的區(qū)別,在于第二個(gè)程序中主循環(huán) main()函數(shù)始終沒有退出,而第一個(gè)程序,main()函數(shù)退出了。似乎前面LED微微點(diǎn)亮 應(yīng)該與主函數(shù)退出之后,單片機(jī)都干了些啥有關(guān)系。
那么就剩下一個(gè)問(wèn)題:對(duì)于普通的嵌入式系統(tǒng),C語(yǔ)言編程中main()函數(shù)退出之后,程序去哪兒了?
二、程序去哪兒了?
從上面提問(wèn)者書寫的代碼來(lái)看,應(yīng)該是一位C51的愛好者,使用的是C51的編譯器,在一款C51開發(fā)板上愉快的進(jìn)行實(shí)驗(yàn)。他一開始沒有安裝嵌入式程序開發(fā)的慣例 在主程序void main(void)中利用無(wú)限循環(huán)將程序控制在主程序函數(shù)中,就出現(xiàn)了前面實(shí)驗(yàn)結(jié)果中令人迷惑的情況。
“注:他是一個(gè)膽大心細(xì)的人,觀察還挺仔細(xì)的。”
2.1 盤古開天辟地
對(duì)于C語(yǔ)言編程來(lái)說(shuō),所有的用戶程序世界是從主程序main()開始的。給用戶程序開天辟地的任務(wù)是由一小段盤古代碼STARTUP.A51。
51單片機(jī)程序執(zhí)行流程(STARTUP.A51管理Main函數(shù)的執(zhí)行)
下面截取了STARTUP.A51 代碼的一段,可以看到盤古在單片機(jī)RESET之后做了點(diǎn)準(zhǔn)備工作(初始化全局變量、堆棧指針)之后,就直接跳轉(zhuǎn)至:?C_START
NAME ?C_STARTUP ?C_C51STARTUP SEGMENT CODE ?STACK SEGMENT IDATA RSEG ?STACK DS 1 EXTRN CODE (?C_START) PUBLIC ?C_STARTUP CSEG AT 0 ?C_STARTUP: LJMP STARTUP1 RSEG ?C_C51STARTUP STARTUP1: IF IDATALEN <> 0 MOV R0,#IDATALEN - 1 CLR A IDATALOOP: MOV @R0,A DJNZ R0,IDATALOOP ENDIF IF XDATALEN <> 0 MOV DPTR,#XDATASTART MOV R7,#LOW (XDATALEN) IF (LOW (XDATALEN)) <> 0 MOV R6,#(HIGH (XDATALEN)) +1 ELSE MOV R6,#HIGH (XDATALEN) ENDIF CLR A XDATALOOP: MOVX @DPTR,A INC DPTR DJNZ R7,XDATALOOP DJNZ R6,XDATALOOP ENDIF IF PPAGEENABLE <> 0 MOV PPAGE_SFR,#PPAGE ENDIF IF PDATALEN <> 0 MOV R0,#LOW (PDATASTART) MOV R7,#LOW (PDATALEN) CLR A PDATALOOP: MOVX @R0,A INC R0 DJNZ R7,PDATALOOP ENDIF IF IBPSTACK <> 0 EXTRN DATA (?C_IBP) MOV ?C_IBP,#LOW IBPSTACKTOP ENDIF IF XBPSTACK <> 0 EXTRN DATA (?C_XBP) MOV ?C_XBP,#HIGH XBPSTACKTOP MOV ?C_XBP+1,#LOW XBPSTACKTOP ENDIF IF PBPSTACK <> 0 EXTRN DATA (?C_PBP) MOV ?C_PBP,#LOW PBPSTACKTOP ENDIF MOV SP,#?STACK-1 LJMP ?C_START END
上面的代碼也被博文51單片機(jī)程序執(zhí)行流程(STARTUP.A51)中進(jìn)行逐步調(diào)試跟蹤驗(yàn)證過(guò):

2.2 世界盡頭
由于進(jìn)入main()函數(shù)是長(zhǎng)跳轉(zhuǎn),所以main函數(shù)是不會(huì)正常返回到啟動(dòng)程序STARTUP.A51,那么程序去哪了?
在博文單片機(jī)C語(yǔ)言while(1)的問(wèn)題中作者對(duì)于KEIL編譯器和PIC的MAPLAB編譯器對(duì)于main函數(shù)的最后時(shí)光進(jìn)行了反匯編查看。
Keil編譯器
在main函數(shù)的最后,程序增加了一下幾行代碼:
MOV R0, #0x7F CLR A MOV @R0, A DJNZ R0, (3) MOV SP, #0x0C LJMP main
這幾條語(yǔ)句,前4條,是將我們單片機(jī)的內(nèi)存的前128個(gè)地址清零,第5條,是定義堆棧,第6條,是將程序重新跳轉(zhuǎn)到main函數(shù)的首行進(jìn)行執(zhí)行。
MAPLAB編譯器
PIC 單片機(jī)語(yǔ)言程序進(jìn)行跟蹤,發(fā)現(xiàn)main() 函數(shù)最后一條語(yǔ)句為 reset,也就是單片機(jī)直接復(fù)位,這是 MAPLAB編譯器根據(jù) PIC 單片機(jī)特點(diǎn)增加的復(fù)位語(yǔ)句。
總結(jié)
對(duì)于嵌入式系統(tǒng),如果沒有運(yùn)行RTOS,那么程序開發(fā)中的主函數(shù)(main())需要通過(guò)某種機(jī)制使其永遠(yuǎn)愉快的運(yùn)行下去,它沒有終點(diǎn)。如果想從main函數(shù)中退出,具體干什么是由所使用的C語(yǔ)言編譯器決定的。
來(lái)源:TsinghuaJoking
免責(zé)聲明:本文為轉(zhuǎn)載文章,轉(zhuǎn)載此文目的在于傳遞更多信息,版權(quán)歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系小編進(jìn)行處理
-
led
+關(guān)注
關(guān)注
243文章
24594瀏覽量
690792 -
單片機(jī)
+關(guān)注
關(guān)注
6076文章
45494瀏覽量
670258 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67499 -
main
+關(guān)注
關(guān)注
0文章
38瀏覽量
6615
評(píng)論
發(fā)布評(píng)論請(qǐng)先 登錄
單片機(jī)main函數(shù)在中斷函數(shù)里執(zhí)行?
什么叫單片機(jī)?單片機(jī)能干嘛?求解答
單片機(jī)能干嘛?如何學(xué)習(xí)單片機(jī)
怎么去學(xué)習(xí)單片機(jī)? 學(xué)習(xí)單片機(jī)的目的是干嘛?
STM32單片機(jī)DEBUG不能進(jìn)入Main函數(shù)怎么解決?
單片機(jī)還能有什么秘密呢
STM32程序無(wú)法進(jìn)入main函數(shù)的解決方法
單片機(jī) keil c語(yǔ)言字符比較函數(shù)的使用 使用strcmp();
51單片機(jī) 點(diǎn)亮一個(gè)LED LED閃爍
單片機(jī)啟動(dòng)過(guò)程: main之前干了啥
STM32系列單片機(jī)在進(jìn)入main函數(shù)前都在干些什么?
單片機(jī) keil調(diào)試的時(shí)候進(jìn)入不了main函數(shù)
C語(yǔ)言編程中main函數(shù)退出后程序去哪兒了?
單片機(jī)main函數(shù)結(jié)束干嘛去了?