標籤:
在彙編中 使用位置無關碼
b,bl
在c語言中 使用位置無關碼
不用全域變數 不用靜態變數
位置無關碼:CPU取指時,總是相對於本條執行指令的相對位址去取指。比如指行一個ADD指令時,PC要取下一指令的地址,就在原來的基礎上+4。這就不管你代碼放在儲存空間的任何位置,只要他們的相對位址沒有改變,就能正常執行程式。一般上電複位那幾條語句就必須是位置無關碼指令。
位置相關碼:可以這樣來說,就是CPU每次取指都從絕對位置去取,而不是上面的相對位置。這個絕對位址就是相對起始地址0來說的。這樣,就要求你在存放程式時,必須給串連指令碼所規定的一樣,把代碼放到指定位置
1.A排在第一的位置,B排在第二的位置
2.A排在B的前面
這兩種情況,都說明的A和B的位置關係,而第一種跟位置相關,屬於絕對位址;而第二種情況則跟位置無關,屬於相對位址。
位置無關與位置相關代碼是關於arm程式在跳轉時的定址方式的兩種,一般情況下兩種方法都能達到跳轉到目的地址的目標,但是在某些特定的環境下,兩種跳轉方法得到的結果相關較大。
位置無關代碼的跳轉可通過“B或BL 標號”命令執行,當執行B或BL命令實現跳轉時,實際的二進位代碼在跳轉時是執行:計算可執行代碼中目標地址到當前PC值處的距離,然後把該距離值加上當前的PC值,然後賦值給PC寄存器實現跳轉,該跳轉方法由於指令的地址域只有26位,所以它只能向前/向後定址32M位地址,如果目標地址到當前PC值的距離大於該值時,可使用偽指令“ADR和ADRL PC,=標號地址”實現跳轉,實際執行過程是先計算目標址址到當前PC的距離,然後把當前PC值加上距離值賦值到目標寄存器PC中,實現跳轉,ADR與B或BL功能類似,但ADRL可以實現全部範圍內的跳轉,其通過把目標地址與當前PC的距離值儲存到一個緩衝字中,然後把緩衝字中的值載入到寄存器PC中。
位置相關跳轉也可以叫絕對位置跳轉,一般使用偽指令LDR PC,=label實現跳轉到label標號的連結地址中,絕對位址也就是連結地址。這裡位置相關及位置無關本質上的區別其實是連結地址與運行地址的區別。
在無作業系統中的裸機代碼中,如果連結的位移基址為0,則絕對位置跳轉與相對位置跳轉的效果是一樣的,而對於一些把可執行代碼拷貝到ram中再啟動並執行程式中,連結地址與起始運行地址是不相同的,一般地連結地址是一個ram邏輯地址內的一個數值,而運行地址則是代碼燒寫的flash等儲存空間件的邏輯地址,一般是0地址。連結的位移地址可以通過在編譯時間通過在連結指令碼或Makefile中指定。
在完成可執行代碼從flash到ram的拷貝後,通過LDR PC,=label指令跳轉到記憶體中執行程式,而在這之前執行的代碼跳轉必須是位置無關的,否則會出現跑飛的異常。
B label BL label //位置無關跳轉到label
ADR R0,label ADRL R0,=label //擷取label到當前程式的位移距離
ADR PC,label ADRL PC,=label //位置無關跳轉到label
LDR PC,=label //位置相關的絕對位置跳轉
LDR R0,=label //擷取label到當前程式的位移距離,注意這裡不是擷取label的(連結地址)絕對位址
LDR R0,=0x500000C0
LDR R1,[R0]
LDR R2,=0x00
STR R2,[R0]
LDR R0,=label載入label資料到寄存器R0中,如果label大於255則把LDR翻譯成上述位置無關的偽指令,如果小於255則直接是用LDR指令進行立即數定址方式
參考:
http://blog.chinaunix.net/uid-10696433-id-2935776.html
http://m.blog.csdn.net/blog/zhaigch/39433601
位置無關碼 位置相關碼