main函数的前世今生

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

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

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


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

[c-sharp]  view plain copy
  1. Reset_Handler   PROC  
  2.                 EXPORT  Reset_Handler             [WEAK]  
  3.                 IMPORT  __main  
  4.                 LDR     R0, =__main  
  5.                 BX      R0  
  6.                 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]  view plain copy
  1. static int g_iVal = 12;  

 

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


 

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


 

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值