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