2016-12-28 45 views
0

我讀過this tutorial爲什麼需要鏈接腳本和啓動代碼?

我可以按照指南運行代碼。但我有問題。

1)爲什麼我們需要加載地址和運行時地址。據我瞭解,這是因爲我們已經把閃存數據放在閃存上。那麼爲什麼我們不在那裏運行應用程序,但需要啓動代碼將其複製到RAM中?

http://www.bravegnu.org/gnu-eprog/c-startup.html

2)我們爲什麼需要鏈接腳本和啓動代碼在這裏。我能不能像下面那樣構建C源代碼並使用qemu來運行它?

arm-none-eabi-gcc -nostdlib -o sum_array.elf sum_array.c 

非常感謝

回答

0

1)。數據部分包含變量。變量是可變的 - 它們在運行時會發生變化。變量需要在RAM中,以便在運行時可以輕鬆更改。閃存與RAM不同,在運行時不易更改。 Flash包含.data部分中變量的初始值。啓動代碼將.data段從閃存複製到RAM以初始化RAM中的運行時變量。

2)鏈接器腳本:由編譯器創建的目標代碼尚未位於微控制器的存儲器映射中。這是鏈接器的工作,這就是爲什麼你需要鏈接器腳本。鏈接器腳本被輸入到鏈接器,並提供有關係統內存位置和範圍的一些說明。

啓動代碼:從main開始的C程序不是在真空中運行,而是對環境做出一些假設。例如,它假定在執行main之前初始化的變量已經被初始化。當執行main(即「運行時環境」)時,啓動代碼是必需的,以實現所有假定的所有事情。堆棧指針是在執行main之前在啓動代碼中初始化的另一個示例。如果您使用的是C++,則在執行main之前,會從啓動代碼中調用靜態對象的構造函數。

0

1)爲什麼我們需要load-address和run-time地址。

儘管在大多數情況下可以從內存映射ROM中運行代碼,但通常代碼在內存中執行得更快。在某些情況下,ROM和應用程序代碼可能會有更大的RAM壓縮在ROM中,因此可執行代碼可能不會簡單地從ROM中複製,也可以解壓縮 - 允許比可用ROM大得多的應用程序。

在代碼存儲在非內存映射大容量存儲介質(如NAND閃存)中的情況下,它無法在任何情況下直接執行,必須通過某種引導加載程序加載到RAM中。

2)爲什麼我們需要鏈接腳本和啓動代碼。我能不能像下面那樣構建C源代碼並使用qemu來運行它?

鏈接描述文件定義您的目標和應用程序的內存佈局。由於本教程是針對裸機編程的,因此沒有OS爲您處理。同樣,啓動代碼至少需要設置一個初始堆棧指針,初始化靜態數據並跳轉到main。在嵌入式系統中,還需要初始化各種硬件,如PLL,存儲器控制器等。

2

您的第一個問題已在指南中得到解答。

當您在操作系統上加載程序時,您的.data節(基本上非零全局變量)會從「binary」加載到內存中的右側偏移量中,以便當程序啓動那些內存位置代表你的變量有這些值。

unsigned int x=5; 
unsigned int y; 

作爲一名C程序員,您編寫了上面的代碼,並且您希望x在您第一次使用時是5?那麼,如果從閃存引導,裸機,你沒有一個操作系統將這個值複製到你的RAM,有人必須這樣做。進一步的所有.data的東西都必須在閃存中,數字5必須在閃存的某個地方,以便它可以複製到RAM。所以你需要一個flash地址和一個ram地址。兩個地址爲同一件事。

這就開始回答你的第二個問題,對於你編寫的每一行C代碼,你都假設任何函數都可以調用任何其他函數。你想能夠調用函數是嗎?而且你希望能夠有局部變量,並且你希望上面的變量x爲5,並且你可以假設y將爲零,但是,幸好編譯器開始警告這個問題。通用C的最小啓動代碼設置了堆棧指針,它允許你調用其他函數,並且有局部變量,並且函數的長度超過一行或兩行代碼,它將清零.bss,以便上面的y變量是零,它將值5複製到ram中,以便在運行入口點C函數的代碼時x已準備就緒。

如果你沒有操作系統,那麼你必須有代碼來做到這一點,是的,有許多許多沙箱和工具鏈設置爲已經有啓動和鏈接腳本的各種平臺,以便你可以只是

gcc -O myprog.elf myprog.c 

現在,這並不意味着你可以使系統調用沒有... ...系統的printf,FOPEN,等等。但是,如果你下載這些工具鏈的一個它意味着你不確實有寫鏈接器腳本或引導程序。

但它仍然是有價值的信息,請注意啓動代碼和鏈接器腳本也是基於操作系統的程序所必需的,它只是針對您的操作系統的本機編譯器假定您將主要爲該操作系統編寫程序,結果他們在該工具鏈中提供了鏈接器腳本和啓動代碼。

相關問題