在重定位過程中,一般使用位置無關的代碼,也即使用相對跳轉指令。如:bl main
下面我們就跳轉指令的位置無關代碼和位置相關代碼進行比較。
...
bl main
ldr pc, =main
...
經過反組譯碼之後,我們得如下代碼:
...
5000001c: eb00002f bl 500000e0 <main>
50000020: e59ff004 ldr pc, [pc, #4] ; 5000002c <halt+0x8>
...
5000002c: 500000e0 .word 0x500000e0
...
500000e0 <main>:
500000e0: e92d4800 push {fp, lr}
500000e4: e28db004 add fp, sp, #4 ; 0x4
...
一、
由 bl main 產生的機器碼:eb00002f的2進位表示為1110 1011 0000 0000 0000 0000 0010 1111, 其中b[31:28]是條件標誌位,
b[27:25]=101表示這是一條跳轉指令,b[24]如果設定為1,則返回地址被儲存於R14寄存器中;如果為0,表示不儲存返回地址。
b[23:0]為一個有符號數,表示跳轉的目標地址。其計算規則如下:
1. Sign-extending the 24-bit signed (two's complement) immediate to 30 bits.
2. Shifting the result left two bits to form a 32-bit value.
3. Adding this to the contents of the PC, which contains the address of the branch instruction plus 8 bytes.
用上述規則我們得到跳轉的目標地址為(0x2f << 2)+ 8 + 0x1c = 0xe0. 此時,程式跳到0xe0處執行。
二、
由ldr pc, =main產生的反組譯碼代碼 ldr pc, [pc, #4]。此時,pc = 0x20 + 8 + 4 = 0x2c, 即 pc = [0x2c] = 0x500000e0, 於是跳到0x500000e0
處執行,而此時尚未重定位,故此地址不存在,因此將發生錯誤。
由上可見,bl指令使用的是“PC+位移值”的方式跳轉,屬於相對跳轉指令,而位置相關的代碼採用的是直接將跳轉地址載入到PC中,這樣的過程在重定位前往往是會發生錯誤的。因此代碼在重定位前必須使用位置無關的指令。