程序的完整運行過程,在main函數調用之前到底執行了哪些操作?

        很多人都知道程序是從main函數開始執行的,但在main之前執行了什麼卻不夠了解,本文分別介紹Keil調用的ARMCC以及ARM-NONE-EABI-GCC兩個編譯器生成的在main之前的操作:

Keil MDK啓動文件

總結一下MDK的啓動流程: 
1.系統初始化,包括中斷向量表的重新映射 
2.加載RW段(.data段初始化) 
3.加載ZI段(.bss段初始化) 
4.初始化用戶堆棧 
5.初始化Microlib 
6.調用main函數 
        microlib 是缺省 C 庫的備選庫。 它旨在與需要裝入到極少量內存中的深層嵌入式應用程序配合使用。 這些應用程序不在操作系統中運行。 
        microlib 進行了高度優化以使代碼變得很小。 它的功能比缺省 C 庫少,並且根本不具備某些 ISO C 特性。 某些庫函數的運行速度也比較慢,例如,memcpy()。 
       下圖是Keil調用ARMCC的加載到運行的變化視圖: 
這裏寫圖片描述

        稍微解釋下這張圖,從加載加載視圖切換到執行視圖時,代碼存放在ROM中是不用變的,將pc指針指向程序的初始地址就可以依次執行指令,但是已經初始化的全局變量data段與未初始化的全局變量bss段需要從flash中加載到指定的內存地址中。

對於RO與RW段 
        Loadregion_nameBase表示region_name區域的裝載地址 
       “Imageregion_nameBase”表示region_name區域的執行地址 
       “Imageregion_nameLength”表示region_name區域的長度(單位:字節) 
對於ZI段 
       “Imageregion_nameZIBase”表示region_name區域的執行地址 
       “Imageregion_nameZILength”表示region_name區域的長度(單位:字節)

 ARM-NONE-EABI-GCC的crt0啓動流程

        利用arm-none-eabi-gcc編譯器生成ELF文件,將ELF文件通過objdump反彙編可以找出main之前的初始化函數_mainCRTStartup。
        下圖爲ARM7V-M平臺下_mainCRTStartup的大致流程:

這裏寫圖片描述

下面看一下ELF文件中各段的分佈: 
這裏寫圖片描述 
由上圖可知.text後直接跟.data段,但.data段的地址爲RAM的實際地址。

 小結:

        arm-none-eabi-gcc不像armcc有將全局變量的值存儲在flash中,所以沒有像scatter_load函數這樣從flash中加載全局變量到ram中,arm-none-eabi-gcc只能靠加載器將.data段直接加載到ram中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章