简 介:对于嵌入式系统,如果没有运行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文章
3590浏览量
129459 -
C51
+关注
关注
5文章
283浏览量
58087
原文标题:程序结束后去哪儿了?
文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论