For embedded systems, if there is no RTOS running, the main function main() in program development needs to ensure it runs happily forever through some mechanism; it has no endpoint. If you want to exit from the main function, what happens afterwards is determined by the C language compiler being used.
1. Question Raised
In the LED module definition function of the microcontroller, an interesting question was observed. The questioner was conducting basic C51 programming experiments and wrote a simple C51 program as follows:
#include <REGX51.H>
void test(num) {
switch(num) {
case 1: P2_0=0; P2_1=0;
break;
}
}
void main(void) {
test(1);
}
After executing the program, it can be seen that two LEDs on the experimental board are lit, while the other six are surprisingly dimly lit.

If an infinite loop is added to the main program: while(1);, then the “dimly lit” phenomenon will no longer appear on the circuit board.
#include <REGX51.H>
void test(num) {
switch(num) {
case 1: P2_0=0; P2_1=0;
break;
}
}
void main(void) {
test(1);
while(1);
}
The difference between the two situations above is that in the second program, the main loop main() function does not exit, while in the first program, the main() function exits. It seems that the dimly lit LEDs are related to what the microcontroller does after the main function exits.
So, one question remains: For ordinary embedded systems, what happens to the program after the main() function exits in C language programming?
2. Where Does the Program Go?
From the code written by the questioner, it seems that they are a C51 enthusiast using the C51 compiler, happily experimenting on a C51 development board. Initially, they did not follow the convention of embedded program development, using an infinite loop in the main function void main(void) to keep the program controlled within the main function, which led to the confusing experimental results mentioned earlier.
“
Note: They are a bold and meticulous person, with quite careful observations.
”
2.1 The Creation of the World
In C language programming, all user programs start from the main() function. The task of creating the user program world is done by a small segment of Pangu code STARTUP.A51.
Execution flow of the 51 microcontroller program (STARTUP.A51 manages the execution of the main function)
Below is an excerpt from the STARTUP.A51 code, showing that after the microcontroller RESET, Pangu does some preparatory work (initializing global variables, stack pointers) before jumping directly to:<span>?C_START</span>
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
The above code has also been verified through step-by-step debugging in the blog post about the execution flow of the 51 microcontroller program (STARTUP.A51):

2.2 The End of the World
Since entering the main() function is a long jump, the main function does not normally return to the startup program STARTUP.A51, so where does the program go?
In the blog post about the C language while(1) issue of the microcontroller, the author examined the last moments of the main function by disassembling the KEIL compiler and the MAPLAB compiler.
Keil Compiler
At the end of the main function, the program adds a few lines of code:
MOV R0, #0x7F
CLR A
MOV @R0, A
DJNZ R0, (3)
MOV SP, #0x0C
LJMP main
These statements, the first four, clear the first 128 addresses of our microcontroller memory, the fifth defines the stack, and the sixth jumps the program back to the first line of the main function for execution.
MAPLAB Compiler
Tracking the PIC microcontroller language program, it was found that the last statement of the main() function is reset, which means the microcontroller resets directly. This reset statement is added by the MAPLAB compiler according to the characteristics of the PIC microcontroller.
Conclusion
For embedded systems, if there is no RTOS running, the main function (main()) in program development needs to ensure it runs happily forever through some mechanism; it has no endpoint. If you want to exit from the main function, what happens afterwards is determined by the C language compiler being used.
Recently, many friends have asked me for essential materials for programmers, so I dug out some hidden treasures and am sharing them for free!
Scan the QR code on the poster to get it for free.