關(guān)于啟動(dòng)代碼的相關(guān)解釋:
1、AREA指令:偽指令,用于定義代碼段或數(shù)據(jù)段,后跟屬性標(biāo)號(hào)。其中比較重要的一個(gè)標(biāo)號(hào)為“READONLY”或者“READWRITE”,其中“READONLY”表示該段為只讀屬性,聯(lián)系到STM32的內(nèi)部存儲(chǔ)介質(zhì),可知具有只讀屬性的段保存于FLASH區(qū),即0x8000000地址后。而“READONLY”表示該段為“可讀寫(xiě)”屬性,可知“可讀寫(xiě)”段保存于SRAM區(qū),即0x2000000地址后。由此可以從第3、7行代碼知道,堆棧段位于SRAM空間。從第82行可知,中斷向量表放置與FLASH區(qū),而這也是整片啟動(dòng)代碼中最先被放進(jìn)FLASH區(qū)的數(shù)據(jù)。因此可以得到一條重要的信息:0x8000000地址存放的是棧頂?shù)刂穇_initial_sp,0x8000004地址存放的是復(fù)位中斷向量Reset_Handler(STM32使用32位總線,因此存儲(chǔ)空間為4字節(jié)對(duì)齊)。
2、DCD指令:作用是開(kāi)辟一段空間,其意義等價(jià)于C語(yǔ)言中的地址符“&”。因此從第84行開(kāi)始建立的中斷向量表則類似于使用C語(yǔ)言定義了一個(gè)指針數(shù)組,其每一個(gè)成員都是一個(gè)函數(shù)指針,分別指向各個(gè)中斷服務(wù)函數(shù)。
3、標(biāo)號(hào):前文多處使用了“標(biāo)號(hào)”一詞。標(biāo)號(hào)主要用于表示一片內(nèi)存空間的某個(gè)位置,等價(jià)于C語(yǔ)言中的“地址”概念。地址僅僅表示存儲(chǔ)空間的一個(gè)位置,從C語(yǔ)言的角度來(lái)看,變量的地址,數(shù)組的地址或是函數(shù)的入口地址在本質(zhì)上并無(wú)區(qū)別。
4、第202行中的__main標(biāo)號(hào)并不表示C程序中的main函數(shù)入口地址,因此第204行也并不是跳轉(zhuǎn)至main函數(shù)開(kāi)始執(zhí)行C程序。__main標(biāo)號(hào)表示C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫(kù)函數(shù)里的一個(gè)初始化子程序__main的入口地址。該程序的一個(gè)主要作用是初始化堆棧(對(duì)于程序清單一來(lái)說(shuō)則是跳轉(zhuǎn)__user_initial_stackheap標(biāo)號(hào)進(jìn)行初始化堆棧的),并初始化映像文件,最后跳轉(zhuǎn)C程序中的main函數(shù)。這就解釋了為何所有的C程序必須有一個(gè)main函數(shù)作為程序的起點(diǎn)——因?yàn)檫@是由C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫(kù)所規(guī)定的——并且不能更改,因?yàn)镃/C++標(biāo)準(zhǔn)實(shí)時(shí)庫(kù)并不對(duì)外界開(kāi)發(fā)源代碼。因此,實(shí)際上在用戶可見(jiàn)的前提下,程序在第204行后就跳轉(zhuǎn)至.c文件中的main函數(shù),開(kāi)始執(zhí)行C程序了。
5.PROC 為子程序開(kāi)始,ENDP 為子程序結(jié)束
6.對(duì)于main函數(shù)的理解
事實(shí)上,_main和main是兩個(gè)完全不同的函數(shù)!_main代碼是編譯器自動(dòng)創(chuàng)建的,因此無(wú)法找到_main代碼。MDK文檔中有一句說(shuō)明:it isautomatically craated by the linker when it sees a definition ofmain() .大體意思可以理解為:當(dāng)編譯器發(fā)現(xiàn)定義了main函數(shù),那么就會(huì)自動(dòng)創(chuàng)建_main
_main 和main的關(guān)系
_main 主要做兩件事:其一,C所需的資源;其二,調(diào)用main函數(shù)。這就不難理解為什么在啟動(dòng)代碼調(diào)用的是_main,最后卻能轉(zhuǎn)到main函數(shù)中去執(zhí)行的原因了。