位置無關碼介紹

2021-09-07 04:29:52 字數 3968 閱讀 4214

1. 程式在執行期間動態載入到記憶體;

2. 程式在不同場合與不同程式組合後載入到記憶體(共享的動態鏈結庫);  

3. 在執行期間不同位址相互之間的對映(如bootloader)。   

總結:位置無關**,即該段**無論放在記憶體的哪個位址,都能正確執行。究其原因,是因為**裡沒有使用絕對位址,都是相對位址。而位置相關碼,即它的位址與**處於的位置相關,是絕對位址,如:mov pc ,#0xff;ldr  pc,=0xffff等。如果你的這段**需要實現位置無關,那麼你就不能使用絕對定址指令,否則的話就是位置有關。

ldr:通常都是作載入指令的,但是它也可以作偽指令,通常有兩種不同的表示:

ldr r0,label
表示把label表示的位址上的值存到r0(label為程式標號,label必須是當前指令的-4~4kb範圍內),cpu通過計算偏移值得到,也就是相對位址,是位置無關碼。

ldr r0, =label
如果label是標號,表示把label的位址存到r0中,這裡面出現的「=」預示著這是一條偽指令,這個是取得標號label「絕對位址」,這個絕對位址就是在link的時候確定的,也就是鏈結位址或叫做編譯位址

如果label是立即數,表示把立即數存入r0中。

bl  main /* 位置無關 */
顯然,用ldr時,加不加=號有很大區別:

無=號表示取該標號處的值,位置無關;

有=號表示取該標號的位址,位置相關。

彙編檔案部分**如下:

reset:                  

ldr sp, =4096 @ 設定棧指標,以下都是c函式,呼叫前需要設好棧

bl disable_watch_dog @ 關閉watchdog,否則cpu會不斷重啟

// bl是位置無關碼,相當於:pcnew = pc + 偏移

// pcnew = (4+8) + 0x28 = 0x34

//ldr pc, =disable_watch_dog /* 這樣寫將出錯 */

bl clock_init @ 設定mpll,改變fclk、hclk、pclk

bl memsetup @ 設定儲存控制器以使用sdram

bl copy_steppingstone_to_sdram @ 複製**到sdram中

ldr pc, =on_sdram @ 跳到sdram中繼續執行

on_sdram:

ldr sp, =0x34000000 @ 設定棧指標

ldr lr, =halt_loop @ 設定返回位址

ldr pc, =main @ 呼叫main函式

halt_loop:

b halt_loop

sections 

.rodata align(4) :

.data align(4) :

.bss align(4) :

}

反彙編如下:

30000000 <_start>:

30000000: e3a0da01 mov sp, #4096 ; 0x1000

30000004: eb00000a bl 30000034 30000008: eb00000d bl 30000044 3000000c: eb000026 bl 300000ac 30000010: eb000040 bl 30000118 30000014: e59ff00c ldr pc, [pc, #12] ; 30000028 <.text>

30000018 :

30000018: e3a0d30d mov sp, #872415232 ; 0x34000000

3000001c: e59fe008 ldr lr, [pc, #8] ; 3000002c <.text>

30000020: e59ff008 ldr pc, [pc, #8] ; 30000030 <.text>

30000024 :

30000024: eafffffe b 30000024 30000028: 30000018 andcc r0, r0, r8, lsl r0

3000002c: 30000024 andcc r0, r0, r4, lsr #32

30000030: 30000200 andcc r0, r0, r0, lsl #4

30000034 :

... ...

在彙編檔案中有如下**:   

ldr pc, =on_sdram

這一句等於反彙編中如下**:

30000014:    e59ff00c     ldr    pc, [pc, #12]    ; 30000028 <.text>

其中30000014表示鏈結位址,e59ff00c表示指令機器碼。下面進行分析,首先arm中有兩級流水線,如下圖所示:

pc指向正被取指的指令,而非正在執行的指令(也就是說pc的位址值是正在執行**的位址值加上8)。故pc的位址值應該是此時的指令位址值0x30000014+8,而[pc, #12]表示0x30000014+8+12=0x30000028(8+12=20(十進位制)=0x14(十六進製制))。檢視反彙編中的指令位址為0x30000028所對應的指令機器碼如下:

30000028:30000018andcc    r0, r0, r8, lsl r0

,可以看到0x30000028所對應指令機器碼是30000018。當執行ldr    pc, [pc, #12]就令pc=0x30000018了。當0x30000018位址上沒有對應的**,而pc執行到該位址時,就會出錯,這就是位置相關碼(執行位置相關碼時鏈結位址與執行位址必須一樣)。

ARM下位置無關碼和位置相關碼介紹

由於在學i2c裸板程式中在分析head.s時用到了這個位置無關碼這個概念,並且之前一直不明白位置無關碼,故此次通過查閱其他大神的部落格了解可以得到下面的教程,希望對學arm的朋友有一點幫助。參考 位置無關 即該段 無論放在記憶體的哪個位址,都能正確執行。究其原因,是因為 裡沒有使用絕對位址,都是相對...

連線位址與位置無關指令

在點燈程式中,想看看超過位址空間的結果,於是做了個試驗,修改makefile中的連線位址為0xfffffffc,如下所示。root ubuntu work led on c cat makefile all arm linux gcc c o led.o led.c arm linux gcc c ...

HTTP狀態碼介紹

基本涵蓋了所有問題 http 400 請求無效 http 401.1 未授權 登入失敗 http 401.2 未授權 伺服器配置問題導致登入失敗 http 401.3 acl 禁止訪問資源 http 401.4 未授權 授權被篩選器拒絕 http 401.5 未授權 isapi 或 cgi 授權失敗...