關於編譯鏈結階段指定鏈結位址的作用

2022-09-03 23:18:19 字數 1526 閱讀 9422

首先,記住一句話:程式的鏈結位址必須等於執行位址!

在學習exynos 4412的啟動過程時,發現自己對鏈結位址的作用不是很了解,於是上網查詢了資料做了基本了解,在此做個總結。

上圖是exynos 4412啟動時irom、bl1和bl2在iram中的分布情況。由圖中可以看出,bl2會被載入到0x020_3400的起始位址處(由bl1載入),照理來說,在bl2**編譯鏈結過程中應該將鏈結位址指定到0x0202_3400才是正確的,但是在實際做led實驗(此處bl2的**功能即是按鍵控制led亮滅)過程中發現,將鏈結位址指定為0x0202_0000也照常執行。以下為鏈結指令碼的內容:

sections

.rodata align(4) :

.data align(4) :

.bss align(4) :

}要想明白原因,就得理解鏈結位址的作用。

當鏈結器進行鏈結的時候,首先決定各個目標檔案在最終可執行檔案裡的位置。然後訪問所有目標檔案的位址重定義表,對其中記錄的位址進行重定向   (加上乙個偏移量,即該編譯單元在可執行檔案上的起始位址)。然後遍歷所有目標檔案的未解決符號表,並且在所有的匯出符號表裡查詢匹配的符號,   並在未解決符號表中所記錄的位置上填寫實現位址。最後把所有的目標檔案的內容寫在各自的位置上,再作一些另的工作,就生成乙個可執行檔案。

在上述鏈結指令碼中指定的鏈結位址,即是告訴鏈結器將程式的起始位址設定為0x0202_0000,由此,鏈結器會根據這個設定的起始位址設定程式中位置相關**的位址。假設鏈結位址是0x0202_0000,而程式的起始位址實際是在0x0202_3400,當執行位置無關**時(即要跳轉的執行位址為當前pc的值加上乙個相對偏移量),cpu可以正確找到程式的存放位置,因此執行不會出錯。但是如果存在位置相關**(即鏈結時指定好的固定具體位址,非當前pc值加相對偏移量獲得的相對位址),那麼當cpu跳轉到對應的執行位址處執行時,由於實際的**存放位址執行位址(執行位址由鏈結時根據鏈結位址計算得到)不同,那麼執行就會出錯了。

舉個例子:假設當將鏈結位址指定為0x0202_0000,由此生成的可執行程式中有條位置相關**是 goto 0x0202_1000 ,而實際可執行程式存放在0x0202_3400的起始位址處,那麼實際 goto 0x0202_1000 對應的**就不在0x0202_1000處了,而cpu通過執行 goto 0x0202_1000 跳轉到0x0202_1000處,到那裡去執行**,卻找不到對應的**,因此程式執行就出錯了。

如果鏈結位址與程式在記憶體中的實際存放起始位址不同,當沒有位置相關**時程式執行不會出錯,這就是前面說的led程式可以正常執行的原因。但是如果程式中有位置相關**,那麼當執行到位置相關**時,便會發生錯誤。

因此,程式的鏈結位址必須等於執行位址。

關於鏈結位址

回過頭來看我們的helloworld程式,在makefile中 ttext 0x7c00,鏈結位址為0x7c00,code標號的偏移位址為0x15,則鏈結後其位址為0x7c15,其他函式呼叫此函式時,也就會呼叫位址0x7c15,這時jmpl 0,code語句反彙編後為 假如我們在makefile中改...

20180601 鏈結位址

已知表頭元素為 c 的單鏈表在記憶體中的儲存狀態如下表所示。現將 f 存放於 1014h 處並插入到單鏈表中,若 f 在邏輯上位於 a 和 e 之間,則 a,e,d 的 鏈結位址 依次是 1010h,1014h,1004h 1010h,1004h,null 1014h,1010h,1004h 101...

鏈結位址和儲存位址

什麼是儲存位址呢?我們知道,我們編寫的c 會被編譯成彙編指令,進一步變成機器碼,最後載入到arm的記憶體中。也就是說我們的彙編指令被儲存在記憶體之中,而指令對應的位址,就是他的 儲存位址 其實 儲存位址 的值,一直由pc這個暫存器所記載著。想改變 儲存位址 的值直接改變pc好了 再說鏈結位址,他是指...