1. 程式人生 > >什麼是重定位?為什麼需要重定位?(嵌入式下)

什麼是重定位?為什麼需要重定位?(嵌入式下)

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

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這樣的問題,就需要使用重定位這種方式解決上面的問題了。那什麼是重定位呢?重定位就是在連結地址跟執行地址不同的情況下,執行一段位置無關碼,這段位置無關碼的作用就是將原來的那份程式碼全部複製到連結地址那裡去,然後自己再長跳轉到新的那份程式碼的剛剛執行的那個位置。這樣就實現了連結地址跟執行地址一致的情況了。

3、為什麼需要重定位?

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