什么是重定位?為什么需要重定位?【轉】


一、必須知道的幾個概念。

1、鏈接地址和運行地址。

①運行地址,顧名思義就是程序運行的時候的地址,也就是你用工具將代碼下載到RAM的那個地址,也叫加載地址。

②鏈接地址,由鏈接腳本指定的地址。為什么需要鏈接腳本指定地址呢?你想一下,在c語言編程中,當我們需要調用一個A函數的時候,編譯器是怎么找到這個A函數?編譯器肯定是知道它被放在哪里才可以找到它。那就是鏈接腳本的作用,鏈接腳本其實在程序被執行之前都已經指定A函數一個地址編號,以后所有的函數調用我們都會去這個地址編號那里尋找A函數。有點類似於c語言的指針變量。

2、位置有關碼與位置無關碼。

①位置有關碼,就是這句代碼的執行正確與否還需要取決於當前的地址,也就是說跟地址已經綁定了的,例如:ldr PC, _main,就是PC指針必須跳轉到_main(函數名就是一個地址)這個地址去,代碼執行成功與否就相當於受到了這個地址的約束,假如這個地址的內容不存放_main這個函數,就會出錯了。

②位置無關碼,就是這句代碼在哪里運行都可以的,跟所處的地址無關,跟位置有關碼相反。

二、重定位需要理解的一些問題。

1、鏈接地址跟運行地址不同的情況下會出現什么情況?

答:以上面舉的函數A為例,當鏈接地址跟運行地址不同的時候,假如鏈接地址是0x1000,運行地址(加載地址)是0x0000,鏈接腳本指定函數A將來是要存放到(基地址+偏移量)=0x1000+0x0001=0x1001地址的,但是程序在下載的時候卻把這個程序下載到0x0000,所以函數A的地址實際上是存放在(基地址+偏移量)=0x0000+0x0001=0x0001這個地址的。當程序運行到一行位置有關碼例如:ldr PC, A ,編譯器首先就會按照鏈接腳本指定的A的那個地址0x1001尋找A函數,但是因為加載地址跟鏈接地址不同的原因,實際上A函數已經被放到了0x0001,所以執行就會出錯。所以,當這兩個地址不同的時候,執行一段位置有關碼的時候就會發生不可預估的錯誤。

2、為什么會出現鏈接地址跟運行地址不同的情況?

答:當一塊芯片啟動的時候,依靠內部的SRAM,可以運行一小段代碼,而因為DDR還沒初始化,注定了開始的運行地址是在內部SRAM中的。當我們需要運行一個操作系統,那么點的內存怎么夠運行呢?所以這時候就需要初始化DDR才可,而因為我們知道這代碼將來都是在DDR上面運行的,所以鏈接腳本指定的鏈接地址肯定是DDR上面的地址,所以這就出現了鏈接地址跟運行地址不同的情況了。

3、什么是重定位?

答:由於出現1這樣的問題,就需要使用重定位這種方式解決上面的問題了。那什么是重定位呢?重定位就是在鏈接地址跟運行地址不同的情況下,執行一段位置無關碼,這段位置無關碼的作用就是將原來的那份代碼全部復制到鏈接地址那里去,然后自己再長跳轉到新的那份代碼的剛剛執行的那個位置。這樣就實現了鏈接地址跟運行地址一致的情況了。

4、為什么需要重定位?

答:就是鏈接地址跟運行地址不同,在這個情況下我們可以有兩種方案:
①全部使用位置無關碼。
②進行重定位讓這兩個地址相同。
我們知道,如果是一個小代碼,使用①時可以的,但是一個大的代碼文件很難保證全部都使用位置無關碼的,這也是不現實的,所以必須使用重定位解決這個問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM