微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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



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

分类: STM32F 开发工具   5878人阅读  评论(11)  收藏  举报

//=====================================================================
//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函数并不是起点。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐