main函数从哪来?

了解C语言的小伙伴,一定会好奇为什么编程都会从main函数开始执行。相信很多学过的人都只是知道一个程序是从main函数这个入口进入的,但main函数又是从哪里来的呢?

对于在电脑上编程,如在windows/Linux上,main函数是由操作系统调用的,main函数完成后,会给操作系统返回值。

对于最简单的嵌入式程序,CPU从上电开始,需要执行以下步骤:

  1. 从启动文件的代码开始执行程序。
  2. 启动代码跳转到main函数
  3. main函数结束后返回启动文件也就是说,main函数是由人为设定的,并不一定要叫做main函数。

启动文件:

因进入main函数后程序是以C语言编写,C语言中的函数实现需要出入栈,因此启动文件在跳转到main函数前需要先设置栈。完成栈的设置后,启动文件会做一些硬件方面的初始化工作,如内存的初始化。下面将以之前的代码为例进行讲解:

随后调用main函数,设置main函数的返回地址。

main函数返回后,启动文件还会进行一些清理工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@******************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************

.extern main
.text
.global _start
_start:
Reset:
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
// bl是位置无关码,相当于:PCnew = PC + 偏移
// PCnew = (4+8) + 0x28 = 0x34

//ldr pc, =disable_watch_dog /* 这样写将出错 */

bl clock_init @ 设置MPLL,改变FCLK、HCLK、PCLK
bl memsetup @ 设置存储控制器以使用SDRAM
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
on_sdram:
ldr sp, =0x34000000 @ 设置栈指针
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop

这里以SDRAM程序的启动文件为例,程序流程如下:

  1. 关闭看门狗,否则程序会不断重启。
  2. 初始化SDRAM,然后将程序拷贝到SDRAM中执行。
  3. 设置栈指针。
  4. 跳转到main函数。
  5. 设置main函数返回后进入一个死循环,防止程序跑飞。

main函数从哪来?
http://atime.cc/2017/02/07/main函数从哪来?/
作者
ATIME
发布于
2017年2月7日
许可协议