嵌入式程序执行完之后去哪儿了呢?
2022/2/9 12:44:40
本文主要是介绍嵌入式程序执行完之后去哪儿了呢?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
简 介: 对于嵌入式系统,如果没有运行RTOS,那么程序开发中的 主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。
关键词
: C51,main,程序退出
§01 问题提出
今天在CSDN的 单片机led模块定义函数的问题 中看到一个有趣的问题。
一个简单的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函数的执行)
下面截取了 STARTUP.A51 代码的一段,可以看到盘古在单片机 RESET 之后做了点准备工作(初始化全局变量、堆栈指针)之后,就直接跳转至:?C_START
$NOMOD51 ;------------------------------------------------------------------------------ ; This file is part of the C51 Compiler package ; Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc. ; Version 8.01 ; ; *** <<< Use Configuration Wizard in Context Menu >>> *** ;------------------------------------------------------------------------------ ; STARTUP.A51: This code is executed after processor reset. ; ; To translate this file use A51 with the following invocation: ; ; A51 STARTUP.A51 ; ; To link the modified STARTUP.OBJ file to your application use the following ; Lx51 invocation: ; ; Lx51 your object file list, STARTUP.OBJ controls ; ;------------------------------------------------------------------------------ ; Standard SFR Symbols ACC DATA 0E0H B DATA 0F0H SP DATA 81H DPL DATA 82H DPH DATA 83H 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 ; This code is required if you use L51_BANK.A51 with Banking Mode 4 ;<h> Code Banking ; <q> Select Bank 0 for L51_BANK.A51 Mode 4 #if 0 ; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4. EXTRN CODE (?B_SWITCH0) CALL ?B_SWITCH0 ; init bank mechanism to code bank 0 #endif ;</h> LJMP ?C_START END
上面的代码也被博文 51单片机程序执行流程(STARTUP.A51) 中进行逐步调试跟踪验证过:
▲ 图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语言编译器决定的。
■ 相关文献链接:
- 单片机led模块定义函数的问题-嵌入式-CSDN问答
- 51单片机程序执行流程(STARTUP.A51管理Main函数的执行)
- 51单片机程序执行流程(STARTUP.A51)
- 单片机C语言while(1)的问题
● 相关图表链接:
- 图1.1 实验板上的未点亮的LED居然微微发亮
- 图1.2 实验板上后面六个LED就不再点亮了
- 图2.1.1 显示LJMP C_START 就是进入 main() 程序
这篇关于嵌入式程序执行完之后去哪儿了呢?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南