0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

单片机main()函数退出之后,程序会跑去哪里?

dyquk4xk2p3d 来源:TsinghuaJoking 2023-03-30 10:01 次阅读

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

一、问题提出

单片机led模块定义函数中看到一个有趣的问题。提问者在进行基本的C51编程实验,编写了一个简单的C51程序如下:

#include

voidtest(num){
switch(num){
case1:P2_0=0;P2_1=0;
break;
}
}

voidmain(void){
test(1);
}

程序执行完之后,可以看到实验板上的有两个LED被点亮,另外六个居然微微发亮。

a8229fca-ce8a-11ed-bfe3-dac502259ad0.png

如果在主程序中,增加一个无限循环:while(1); ,则电路板上的就不再会出现“微微点亮”的现象了。

#include

voidtest(num){
switch(num){
case1:P2_0=0;P2_1=0;
break;
}
}

voidmain(void){
test(1);
while(1);
}
a8c10372-ce8a-11ed-bfe3-dac502259ad0.png

上面两种情况的区别,在于第二个程序中主循环 main()函数始终没有退出,而第一个程序,main()函数退出了。似乎前面LED微微点亮 应该与主函数退出之后,单片机都干了些啥有关系。

那么就剩下一个问题:对于普通的嵌入式系统,C语言编程中main()函数退出之后,程序去哪儿了

二、程序去哪儿了?

从上面提问者书写的代码来看,应该是一位C51的爱好者,使用的是C51的编译器,在一款C51开发板上愉快的进行实验。他一开始没有安装嵌入式程序开发的惯例 在主程序void main(void)中利用无限循环将程序控制在主程序函数中,就出现了前面实验结果中令人迷惑的情况。

注:他是一个胆大心细的人,观察还挺仔细的。

2.1 盘古开天辟地

对于C语言编程来说,所有的用户程序世界是从主程序main()开始的。给用户程序开天辟地的任务是由一小段盘古代码STARTUP.A51。

51单片机程序执行流程(STARTUP.A51管理Main函数的执行)

下面截取了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)中进行逐步调试跟踪验证过:

a92449c8-ce8a-11ed-bfe3-dac502259ad0.png

2.2 世界尽头

由于进入main()函数是长跳转,所以main函数是不会正常返回到启动程序STARTUP.A51,那么程序去哪了?

在博文单片机C语言while(1)的问题中作者对于KEIL编译器和PIC的MAPLAB编译器对于main函数的最后时光进行了反汇编查看。

Keil编译器

在main函数的最后,程序增加了一下几行代码:

MOVR0,#0x7F
CLRA
MOV@R0,A
DJNZR0,(3)
MOVSP,#0x0C
LJMPmain

这几条语句,前4条,是将我们单片机的内存的前128个地址清零,第5条,是定义堆栈,第6条,是将程序重新跳转到main函数的首行进行执行。

MAPLAB编译器

PIC 单片机语言程序进行跟踪,发现main() 函数最后一条语句为 reset,也就是单片机直接复位,这是 MAPLAB编译器根据 PIC 单片机特点增加的复位语句。

总结

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

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136614
  • 函数
    +关注

    关注

    3

    文章

    4326

    浏览量

    62553
  • RTOS
    +关注

    关注

    22

    文章

    811

    浏览量

    119566
  • main
    +关注

    关注

    0

    文章

    38

    浏览量

    6156
  • maplab
    +关注

    关注

    0

    文章

    3

    浏览量

    1258

原文标题:单片机main()函数退出之后,程序会跑去哪里?

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    单片机main函数在中断函数里执行?

    最近看了硬汉分享的一个内容:为什么复位中断服务程序里面直接调用的main函数,难道所有程序都在复位中断里面执行的?
    发表于 10-24 11:04 954次阅读

    请问单片机main函数是执行一次,还是反复执行?

    ; //电机运行一段时间motor = 0;//电机停}按程序逻辑,电机应该是运行一就停止的,但是下载到板子之后,电机一直运行。在程序最后加了while死循环
    发表于 03-20 08:42

    请问单片机main函数是执行一次还是反复执行?

    请问单片机main函数是执行一次,还是反复执行?
    发表于 10-19 06:25

    请问单片机main函数是执行一次还是反复执行?

    motor = 0;//电机停 } 按程序逻辑,电机应该是运行一就停止的,但是下载到板子之后,电机一直运行。 在程序最后加了while死循环之后
    发表于 10-23 06:20

    AVR单片机的延时函数程序免费下载

    本文档的主要内容详细介绍的是AVR单片机的延时函数程序免费下载
    发表于 11-16 08:00 7次下载
    AVR<b class='flag-5'>单片机</b>的延时<b class='flag-5'>函数</b><b class='flag-5'>程序</b>免费下载

    单片机学习教程之C程序的简单介绍

    包含头文件:现学习的是C51 单片机,所以需要的头文件是#include《reg51.h》程序的主函数main 函数
    发表于 11-19 17:24 12次下载

    深度剖析C语言的main函数

    main的返回值 main函数的返回值用于说明程序退出状态。如果返回0,则代表程序正常
    的头像 发表于 12-18 17:07 4387次阅读

    STM32程序无法进入main函数的解决方法

    很多人在基于STM32单片机项目开发过程中,遇到STM32程序无法进入main的现象,在这篇文将分享STM32程序无法进入
    的头像 发表于 07-22 16:18 1.6w次阅读

    单片机 keil c语言字符比较函数的使用 使用strcmp();

    (const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。菜鸟的链接32单片机中的使用示例1.要在单片机中使用我们要先添加头文件:string.h不然程序
    发表于 11-21 15:06 17次下载
    <b class='flag-5'>单片机</b> keil  c语言字符比较<b class='flag-5'>函数</b>的使用 使用strcmp();

    STM32系列单片机在进入main函数前都在干些什么?

    在刚开始学习单片机的时候,一直以为程序启动后就直接进入到了main函数,但是随着学习的深入才发现,程序在进入
    发表于 11-23 18:21 12次下载
    STM32系列<b class='flag-5'>单片机</b>在进入<b class='flag-5'>main</b><b class='flag-5'>函数</b>前都在干些什么?

    单片机 keil调试的时候进入不了main函数

    单片机 keil调试的时候进入不了main函数
    发表于 12-03 20:51 6次下载
    <b class='flag-5'>单片机</b> keil调试的时候进入不了<b class='flag-5'>main</b><b class='flag-5'>函数</b>

    C语言编程中main()函数退出之后程序去哪儿了

    对于嵌入式系统,如果没有运行RTOS,那么程序开发中的主函数main()需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数
    的头像 发表于 03-22 17:44 2709次阅读

    C语言编程中main函数退出程序去哪儿了?

    PIC 单片机语言程序进行跟踪,发现main() 函数最后一条语句为 reset,也就是单片机直接复位,这是 MAPLAB编译器根据 PIC
    发表于 05-31 15:28 415次阅读
    C语言编程中<b class='flag-5'>main</b><b class='flag-5'>函数</b><b class='flag-5'>退出</b>后<b class='flag-5'>程序</b>去哪儿了?

    main函数不一定就是程序入口

    写个测试代码,代码中有main函数,也有test函数,test就是刚才我们说的入口,不过得指定退出方式,要不然程序运行的时候会出问题。
    的头像 发表于 06-15 17:12 640次阅读

    单片机main函数结束干嘛去了?

    单片机main函数结束干嘛去了?
    的头像 发表于 10-18 17:37 703次阅读
    <b class='flag-5'>单片机</b><b class='flag-5'>main</b><b class='flag-5'>函数</b>结束干嘛去了?