大家好,我是写代码的篮球球痴,转发一篇卓老师的文章,文章中的内容我之前做单片机的时候也有遇到过。

推荐给大家看看~


简 介: 对于嵌入式系统,如果没有运行RTOS,那么程序开发中的 主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。
关键词C51main程序退出

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

程序结束后去哪儿了?相关推荐

  1. MATLAB收取邮件,Matlab 程序结束后发送短信或者邮件

    近期,在服务器上运行matlab程序,由于数据比较多,程序比较复杂,运行时间不固定,而且需要经常改变参数,重复运行几次,所以不清楚程序何时结束,以便于修改参数,继续运行.开始有时间就看看程序是否运行结 ...

  2. 单片机的程序结束后都干嘛去了?

    对于嵌入式系统,如果没有运行RTOS,那么程序开发中的主函数main()需要通过某种机制使其永远愉快的运行下去,它没有终点.如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的. 一. ...

  3. 阳江市2021高考成绩查询一下,广东省阳江市2021年高级会计师考试结束后去哪查成绩?...

    广东省阳江市2021年高级会计职称考试已经结束,很多考生都很迫切的想知道自己的成绩,那么,阳江高级会计师成去哪查?小编来为大家解答,快来了解一下吧! 高级会计成绩查询时间 2021年高级会计师考试成绩 ...

  4. 考研结束后去政审时穿的鞋子

    考研收到政审通知后,烈日下,我记得十分清楚的是,穿着这双鞋去的. 他叫: ABPG051-2 前后有三双,第一双(穿着去政审的一双)被我妈扔了. 第二双因为脱胶被我妈扔了. 第三双留下了, 但是同样款 ...

  5. java static变量销毁_JAVA里static 变量在程序执行结束后是否被消毁

    static变量是属于类的,一般情况下,程序执行结束后,类所占空间会被回收, static变量自然就被销毁了. 如下所示: public class StaticVar{ public static ...

  6. C语言输入end时结束程序,给大家一个程序,输入多个字符串以END结束后排序,这个程序运行,即结果都是对的。...

    给大家一个程序,输入多个字符串以END结束后排序,这个程序运行,即结果都是对的. /*输入多个字符串以END结束后排序*/ #include #include main() {char a[20][3 ...

  7. 错误调试:Ubuntu-Tensorflow ,程序手动结束后,GPU的显存没有被释放

    如题:Ubuntu-Tensorflow ,程序被手动强行结束后(win+c),程序所占用的GPU的显存没有被释放掉,影响下次运行,会出现以下错误: failed to allocate 4.75G ...

  8. 检测到已经有其他更新程序正在运行,请结束后再试的解决

    每次打开易语言,都会提示检测到已经有其他更新程序正在运行,请结束后再试,原因是安装了易语言编程助手,不知道除了什么错误导致即使关闭自动更新,每次打开还是会提示. 我猜测如果重新下载安装可能会解决问题. ...

  9. 编程统计候选人的得票数。设有3个候选人zhang、li、wang(候选人姓名不区分大小写),10个选民,选民每次输入一个得票的候选人的名字,若选民输错候选人姓名,则按废票处理。选民投票结束后程序自动显

    编程统计候选人的得票数.设有3个候选人zhang.li.wang(候选人姓名不区分大小写),10个选民,选民每次输入一个得票的候选人的名字,若选民输错候选人姓名,则按废票处理.选民投票结束后程序自动显 ...

最新文章

  1. 用snap在ubuntu上构建 Microk8s,使用kubectl,部署应用
  2. Nature:揭示大脑中的免疫记忆
  3. python常用函数-python常用魔法函数
  4. jQuery hash
  5. 变电站越级跳闸的几大原因(转载)
  6. 【secureCRT】如何在secureCRT上设置常用的快捷输出按钮栏
  7. python爬虫今日头条街拍美图开发背景_分析Ajax请求并抓取今日头条街拍美图:爬取详情页的url与实际页面上显示不符...
  8. php 处理树形数据,php实现的树形结构数据存取类实例
  9. 网易云信流媒体服务端架构设计与实现
  10. android gridview控件使用详解_Android开发实现自定义日历、日期选择控件
  11. WatiN-Html元素的操作
  12. 查看华为应用商店APPID
  13. 正则去除包裹的大括号
  14. 开源巨献:2017 年 Google 开源了这些超赞的项目
  15. Windows10上安装Keras 和 TensorFlow-GPU
  16. 渗透之——Metasploit命令及模块
  17. 小心 transmittable-thread-local 的这个坑
  18. 学计算机高考英语听力考试时间,北京:2020年高考英语听力机考问答
  19. 赵小楼《天道》《遥远的救世主》深度解析(39)芮小丹的恋爱态度:敞亮
  20. 初期投资60万7-11加盟模式在华将变通

热门文章

  1. linux的du使用方法
  2. 经常使用的 WEB server
  3. 分布式资本沈波:未来区块链杀手级应用将出现在“+区块链”
  4. 张震博士:SDT是未来安防发展方向
  5. 002 exercises
  6. rpmbuild FILE
  7. POJ——字符串插入
  8. JAVA中protected的作用
  9. git中使用fork
  10. python 去掉空格_如何从Python DataFrame中去除空格在这个例子中