加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

main函数之前究竟发生了什么?

发布时间:2020-12-15 07:02:07 所属栏目:百科 来源:网络整理
导读:http://blog.csdn.net/norains/article/details/6052029 main函数之前究竟发生了什么? 分类:?STM32F?开发工具 2010-12-03 10:12 ? 5878人阅读 ? 评论(11) ? 收藏 ? 举报 flash import wizard linker 编译器 exception //=================================

http://blog.csdn.net/norains/article/details/6052029



main函数之前究竟发生了什么?

分类:?STM32F?开发工具 ? 5878人阅读? 评论(11)? 收藏? 举报
flash import wizard linker 编译器 exception

//=====================================================================
//TITLE:
//??? main函数之前究竟发生了什么?
//AUTHOR:
//??? norains
//DATE:
//??? Friday? 3-December-2010
//Environment:
//??? MDK 4.1
//=====================================================================

?

??? ?当使用MFC时,我们会认为入口函数是:: InitInstance;当使用WIN32 API时,我们会认为入口函数是WinMain;当我们写个纯粹的C++程序时,入口函数又变成了main;可当我们进入到嵌入式领域,却发现main函数之前还有一段启动代码!

?

???? 究竟在main函数之前,发生了什么?如果你觉得已经明白了这个过程,那么请试着回答这个问题:程序是存储到FLASH中的,运行时static变量地址是指向RAM,那么这些static变量的初始值是如何映射到RAM中的?

?

???? 我们以STM32F10x的启动代码为例,先看看其完整的源码:

[c-sharp]? view plain copy
  1. ;/*****************************************************************************/??
  2. ;/*?STM32F10x.s:?Startup?file?for?ST?STM32F10x?device?series??????????????????*/??
  3. ;/*?<<<?Use?Configuration?Wizard?in?Context?Menu?>>>??????????????????????????*/??
  4. /*?This?file?is?part?of?the?uVision/ARM?development?tools.???????????????????*/??
  5. /*?Copyright?(c)?2005-2007?Keil?Software.?All?rights?reserved.???????????????*/??
  6. /*?This?software?may?only?be?used?under?the?terms?of?a?valid,?current,???????*/??
  7. /*?end?user?licence?from?KEIL?for?a?compatible?version?of?KEIL?software??????*/??
  8. /*?development?tools.?Nothing?else?gives?you?the?right?to?use?this?software.?*/??
  9. ??
  10. ??
  11. //?<h>?Stack?Configuration??
  12. //???<o>?Stack?Size?(in?Bytes)?<0x0-0xFFFFFFFF:8>??
  13. //?</h>??
  14. Stack_Size??????EQU?????0x00000200??
  15. ????????????????AREA????STACK,?NOINIT,?READWRITE,?ALIGN=3??
  16. Stack_Mem???????SPACE???Stack_Size??
  17. __initial_sp??
  18. //?<h>?Heap?Configuration??
  19. //???<o>??Heap?Size?(in?Bytes)?<0x0-0xFFFFFFFF:8>??
  20. //?</h>??
  21. Heap_Size???????EQU?????0x00000000??
  22. ????????????????AREA????HEAP,?ALIGN=3??
  23. __heap_base??
  24. Heap_Mem????????SPACE???Heap_Size??
  25. __heap_limit??
  26. ????????????????PRESERVE8??
  27. ????????????????THUMB??
  28. ;?Vector?Table?Mapped?to?Address?0?at?Reset??
  29. ????????????????AREA????RESET,?DATA,?READONLY??
  30. ????????????????EXPORT??__Vectors??
  31. __Vectors???????DCD?????__initial_sp??????????????;?Top?of?Stack??
  32. ????????????????DCD?????Reset_Handler?????????????;?Reset?Handler??
  33. ????????????????DCD?????NMI_Handler???????????????;?NMI?Handler??
  34. ????????????????DCD?????HardFault_Handler?????????;?Hard?Fault?Handler??
  35. ????????????????DCD?????MemManage_Handler?????????;?MPU?Fault?Handler??
  36. ????????????????DCD?????BusFault_Handler??????????;?Bus?Fault?Handler??
  37. ????????????????DCD?????UsageFault_Handler????????;?Usage?Fault?Handler??
  38. ????????????????DCD?????0?????????????????????????;?Reserved??
  39. ????????????????DCD?????0?????????????????????????;?Reserved??
  40. ????????????????DCD?????SVC_Handler???????????????;?SVCall?Handler??
  41. ????????????????DCD?????DebugMon_Handler??????????;?Debug?Monitor?Handler??
  42. ????????????????DCD?????PendSV_Handler????????????;?PendSV?Handler??
  43. ????????????????DCD?????SysTick_Handler???????????;?SysTick?Handler??
  44. ????????????????;?External?Interrupts??
  45. ????????????????DCD?????WWDG_IRQHandler???????????;?Window?Watchdog??
  46. ????????????????DCD?????PVD_IRQHandler????????????;?PVD?through?EXTI?Line?detect??
  47. ????????????????DCD?????TAMPER_IRQHandler?????????;?Tamper??
  48. ????????????????DCD?????RTC_IRQHandler????????????;?RTC??
  49. ????????????????DCD?????FLASH_IRQHandler??????????;?Flash??
  50. ????????????????DCD?????RCC_IRQHandler????????????;?RCC??
  51. ????????????????DCD?????EXTI0_IRQHandler??????????;?EXTI?Line?0??
  52. ????????????????DCD?????EXTI1_IRQHandler??????????;?EXTI?Line?1??
  53. ????????????????DCD?????EXTI2_IRQHandler??????????;?EXTI?Line?2??
  54. ????????????????DCD?????EXTI3_IRQHandler??????????;?EXTI?Line?3??
  55. ????????????????DCD?????EXTI4_IRQHandler??????????;?EXTI?Line?4??
  56. ????????????????DCD?????DMAChannel1_IRQHandler????;?DMA?Channel?1??
  57. ????????????????DCD?????DMAChannel2_IRQHandler????;?DMA?Channel?2??
  58. ????????????????DCD?????DMAChannel3_IRQHandler????;?DMA?Channel?3??
  59. ????????????????DCD?????DMAChannel4_IRQHandler????;?DMA?Channel?4??
  60. ????????????????DCD?????DMAChannel5_IRQHandler????;?DMA?Channel?5??
  61. ????????????????DCD?????DMAChannel6_IRQHandler????;?DMA?Channel?6??
  62. ????????????????DCD?????DMAChannel7_IRQHandler????;?DMA?Channel?7??
  63. ????????????????DCD?????ADC_IRQHandler????????????;?ADC??
  64. ????????????????DCD?????USB_HP_CAN_TX_IRQHandler??;?USB?High?Priority?or?CAN?TX??
  65. ????????????????DCD?????USB_LP_CAN_RX0_IRQHandler?;?USB?Low??Priority?or?CAN?RX0??
  66. ????????????????DCD?????CAN_RX1_IRQHandler????????;?CAN?RX1??
  67. ????????????????DCD?????CAN_SCE_IRQHandler????????;?CAN?SCE??
  68. ????????????????DCD?????EXTI9_5_IRQHandler????????;?EXTI?Line?9..5??
  69. ????????????????DCD?????TIM1_BRK_IRQHandler???????;?TIM1?Break??
  70. ????????????????DCD?????TIM1_UP_IRQHandler????????;?TIM1?Update??
  71. ????????????????DCD?????TIM1_TRG_COM_IRQHandler???;?TIM1?Trigger?and?Commutation??
  72. ????????????????DCD?????TIM1_CC_IRQHandler????????;?TIM1?Capture?Compare??
  73. ????????????????DCD?????TIM2_IRQHandler???????????;?TIM2??
  74. ????????????????DCD?????TIM3_IRQHandler???????????;?TIM3??
  75. ????????????????DCD?????TIM4_IRQHandler???????????;?TIM4??
  76. ????????????????DCD?????I2C1_EV_IRQHandler????????;?I2C1?Event??
  77. ????????????????DCD?????I2C1_ER_IRQHandler????????;?I2C1?Error??
  78. ????????????????DCD?????I2C2_EV_IRQHandler????????;?I2C2?Event??
  79. ????????????????DCD?????I2C2_ER_IRQHandler????????;?I2C2?Error??
  80. ????????????????DCD?????SPI1_IRQHandler???????????;?SPI1??
  81. ????????????????DCD?????SPI2_IRQHandler???????????;?SPI2??
  82. ????????????????DCD?????USART1_IRQHandler?????????;?USART1??
  83. ????????????????DCD?????USART2_IRQHandler?????????;?USART2??
  84. ????????????????DCD?????USART3_IRQHandler?????????;?USART3??
  85. ????????????????DCD?????EXTI15_10_IRQHandler??????;?EXTI?Line?15..10??
  86. ????????????????DCD?????RTCAlarm_IRQHandler???????;?RTC?Alarm?through?EXTI?Line??
  87. ????????????????DCD?????USBWakeUp_IRQHandler??????;?USB?Wakeup?from?suspend??
  88. ????????????????AREA????|.text|,?CODE,?READONLY??
  89. ;?Reset?Handler??
  90. Reset_Handler???PROC??
  91. ????????????????EXPORT??Reset_Handler?????????????[WEAK]??
  92. ????????????????IMPORT??__main??
  93. ????????????????LDR?????R0,?=__main??
  94. ????????????????BX??????R0??
  95. ????????????????ENDP??
  96. ;?Dummy?Exception?Handlers?(infinite?loops?which?can?be?modified)??????????????????
  97. NMI_Handler?????PROC??
  98. ????????????????EXPORT??NMI_Handler???????????????[WEAK]??
  99. ????????????????B???????.??
  100. HardFault_Handler/??
  101. ????????????????PROC??
  102. ????????????????EXPORT??HardFault_Handler?????????[WEAK]??
  103. ????????????????B???????.??
  104. ????????????????ENDP??
  105. MemManage_Handler/??
  106. ????????????????PROC??
  107. ????????????????EXPORT??MemManage_Handler?????????[WEAK]??
  108. BusFault_Handler/??
  109. ????????????????EXPORT??BusFault_Handler??????????[WEAK]??
  110. UsageFault_Handler/??
  111. ????????????????EXPORT??UsageFault_Handler????????[WEAK]??
  112. SVC_Handler?????PROC??
  113. ????????????????EXPORT??SVC_Handler???????????????[WEAK]??
  114. DebugMon_Handler/??
  115. ????????????????EXPORT??DebugMon_Handler??????????[WEAK]??
  116. PendSV_Handler??PROC??
  117. ????????????????EXPORT??PendSV_Handler????????????[WEAK]??
  118. SysTick_Handler?PROC??
  119. ????????????????EXPORT??SysTick_Handler???????????[WEAK]??
  120. Default_Handler?PROC??
  121. ????????????????EXPORT??WWDG_IRQHandler???????????[WEAK]??
  122. ????????????????EXPORT??PVD_IRQHandler????????????[WEAK]??
  123. ????????????????EXPORT??TAMPER_IRQHandler?????????[WEAK]??
  124. ????????????????EXPORT??RTC_IRQHandler????????????[WEAK]??
  125. ????????????????EXPORT??FLASH_IRQHandler??????????[WEAK]??
  126. ????????????????EXPORT??RCC_IRQHandler????????????[WEAK]??
  127. ????????????????EXPORT??EXTI0_IRQHandler??????????[WEAK]??
  128. ????????????????EXPORT??EXTI1_IRQHandler??????????[WEAK]??
  129. ????????????????EXPORT??EXTI2_IRQHandler??????????[WEAK]??
  130. ????????????????EXPORT??EXTI3_IRQHandler??????????[WEAK]??
  131. ????????????????EXPORT??EXTI4_IRQHandler??????????[WEAK]??
  132. ????????????????EXPORT??DMAChannel1_IRQHandler????[WEAK]??
  133. ????????????????EXPORT??DMAChannel2_IRQHandler????[WEAK]??
  134. ????????????????EXPORT??DMAChannel3_IRQHandler????[WEAK]??
  135. ????????????????EXPORT??DMAChannel4_IRQHandler????[WEAK]??
  136. ????????????????EXPORT??DMAChannel5_IRQHandler????[WEAK]??
  137. ????????????????EXPORT??DMAChannel6_IRQHandler????[WEAK]??
  138. ????????????????EXPORT??DMAChannel7_IRQHandler????[WEAK]??
  139. ????????????????EXPORT??ADC_IRQHandler????????????[WEAK]??
  140. ????????????????EXPORT??USB_HP_CAN_TX_IRQHandler??[WEAK]??
  141. ????????????????EXPORT??USB_LP_CAN_RX0_IRQHandler?[WEAK]??
  142. ????????????????EXPORT??CAN_RX1_IRQHandler????????[WEAK]??
  143. ????????????????EXPORT??CAN_SCE_IRQHandler????????[WEAK]??
  144. ????????????????EXPORT??EXTI9_5_IRQHandler????????[WEAK]??
  145. ????????????????EXPORT??TIM1_BRK_IRQHandler???????[WEAK]??
  146. ????????????????EXPORT??TIM1_UP_IRQHandler????????[WEAK]??
  147. ????????????????EXPORT??TIM1_TRG_COM_IRQHandler???[WEAK]??
  148. ????????????????EXPORT??TIM1_CC_IRQHandler????????[WEAK]??
  149. ????????????????EXPORT??TIM2_IRQHandler???????????[WEAK]??
  150. ????????????????EXPORT??TIM3_IRQHandler???????????[WEAK]??
  151. ????????????????EXPORT??TIM4_IRQHandler???????????[WEAK]??
  152. ????????????????EXPORT??I2C1_EV_IRQHandler????????[WEAK]??
  153. ????????????????EXPORT??I2C1_ER_IRQHandler????????[WEAK]??
  154. ????????????????EXPORT??I2C2_EV_IRQHandler????????[WEAK]??
  155. ????????????????EXPORT??I2C2_ER_IRQHandler????????[WEAK]??
  156. ????????????????EXPORT??SPI1_IRQHandler???????????[WEAK]??
  157. ????????????????EXPORT??SPI2_IRQHandler???????????[WEAK]??
  158. ????????????????EXPORT??USART1_IRQHandler?????????[WEAK]??
  159. ????????????????EXPORT??USART2_IRQHandler?????????[WEAK]??
  160. ????????????????EXPORT??USART3_IRQHandler?????????[WEAK]??
  161. ????????????????EXPORT??EXTI15_10_IRQHandler??????[WEAK]??
  162. ????????????????EXPORT??RTCAlarm_IRQHandler???????[WEAK]??
  163. ????????????????EXPORT??USBWakeUp_IRQHandler??????[WEAK]??
  164. WWDG_IRQHandler??
  165. PVD_IRQHandler??
  166. TAMPER_IRQHandler??
  167. RTC_IRQHandler??
  168. FLASH_IRQHandler??
  169. RCC_IRQHandler??
  170. EXTI0_IRQHandler??
  171. EXTI1_IRQHandler??
  172. EXTI2_IRQHandler??
  173. EXTI3_IRQHandler??
  174. EXTI4_IRQHandler??
  175. DMAChannel1_IRQHandler??
  176. DMAChannel2_IRQHandler??
  177. DMAChannel3_IRQHandler??
  178. DMAChannel4_IRQHandler??
  179. DMAChannel5_IRQHandler??
  180. DMAChannel6_IRQHandler??
  181. DMAChannel7_IRQHandler??
  182. ADC_IRQHandler??
  183. USB_HP_CAN_TX_IRQHandler??
  184. USB_LP_CAN_RX0_IRQHandler??
  185. CAN_RX1_IRQHandler??
  186. CAN_SCE_IRQHandler??
  187. EXTI9_5_IRQHandler??
  188. TIM1_BRK_IRQHandler??
  189. TIM1_UP_IRQHandler??
  190. TIM1_TRG_COM_IRQHandler??
  191. TIM1_CC_IRQHandler??
  192. TIM2_IRQHandler??
  193. TIM3_IRQHandler??
  194. TIM4_IRQHandler??
  195. I2C1_EV_IRQHandler??
  196. I2C1_ER_IRQHandler??
  197. I2C2_EV_IRQHandler??
  198. I2C2_ER_IRQHandler??
  199. SPI1_IRQHandler??
  200. SPI2_IRQHandler??
  201. USART1_IRQHandler??
  202. USART2_IRQHandler??
  203. USART3_IRQHandler??
  204. EXTI15_10_IRQHandler??
  205. RTCAlarm_IRQHandler??
  206. USBWakeUp_IRQHandler??
  207. ???
  208. ????????????????ALIGN??
  209. ;?User?Initial?Stack?&?Heap??
  210. ????????????????IF??????:DEF:__MICROLIB??
  211. ??????????????????
  212. ????????????????EXPORT??__initial_sp??
  213. ????????????????EXPORT??__heap_base??
  214. ????????????????EXPORT??__heap_limit??
  215. ????????????????ELSE??
  216. ;????????????????IMPORT??__use_two_region_memory??
  217. ????????????????EXPORT??__user_initial_stackheap??
  218. __user_initial_stackheap??
  219. ????????????????LDR?????R1,?=(Stack_Mem?+?Stack_Size)??
  220. ????????????????LDR?????R2,?=?(Heap_Mem?+??Heap_Size)??
  221. ????????????????LDR?????R3,?=?Stack_Mem??
  222. ????????????????BX??????LR??
  223. ????????????????ALIGN??
  224. ????????????????ENDIF??
  225. ????????????????END??


???? 一些旁枝末节和本文的主题无关,我们先不要去理会,只需要知道这个启动代码是设置向量表,然后跳转到__main函数。跳转具体到代码段部分如下:

copy
    Reset_Handler???PROC??
  1. ????????????????ENDP??

?

???? 当大家看到__main函数时,估计应该有不少人认为这个是main函数的别名或是编译之后的名字,否则在启动代码中再也无法找到和main相关的字眼了。可事实是,__main和main是完全两个不同的函数!如果这还不足以让你诧异,那么再告诉你另一个事实:你无法找到__main代码,因为这个是编译器自动创建的!

?

???? 如果你对此还半信半疑,可以查看MDK的文档,会发现有这么一句说明:It is automatically created by the linker when it sees a definition of main()。简单点来说,当编译器发现定义了main函数,那么就会自动创建__main。

?

???? __main函数的出身我们基本搞清楚了,那么现在的问题是,它和main又有什么关系呢?其实__main主要做这么两件事:初始化C/C++所需的资源,调用main函数。初始化先暂时不说,但“调用main函数”这个功能能够让我们解决为什么之前的启动代码调用的是__main,最后却能转到main函数的疑惑。

?

???? 初始化C/C++所需的资源,如果脱离了具体情况,实在很难解释清楚,还是先看看编译出来的汇编代码片段:
?

?

???? 凡是以__rt开头的,都是用来初始化C/C++运行库的;而以__scatterload开头,则是根据离散文件的定义,将代码中的变量映射到相应的内存位置。而回答本文开头的问题,关键就在于__scatterload_copy函数!

?

???? 我们在STM32F10x平台举个简单的例子,首先要明白一点是,该平台的的flash地址以0x08000000为起始,主要是存储代码;而SRAM是以0x20000000为起始,也就是内存。然后C/C++有这么一行代码:

[cpp]? copy
    static?int?g_iVal?=?12;??

?

???? 当我们程序开始跑起来的时候,通过IDE发现,g_iVal被映射到内存地址0x20000000,数值为一个随机数0xFFFFBE00,而不是代码中设置的12,如图:


?

???? 我们让程序继续往下执行,当执行完毕__scatterload_copy之后,我们发现g_iVal这时候已经变成我们所需要的初始值了:


?

???? 接下来就是C/C++库的初始化,最后就是进入到main函数,而此时已经是万事俱备。

?

???? 如果大家只是局限于桌面应用的开发,因为编译出来的程序带有很多操作系统的特性,所以会给我们理解程序的运行带来很大的迷惑,也只有步入嵌入式领域,没有操作系统的支持下赤裸裸地奔跑在CPU之上,才能更好地理解软件是如何运行起来的,也只有这时候我们才能够更清楚知道,原来main函数并不是起点。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读