位置無關代碼碼與位置相關代碼
位置無關與位置相關代碼是關于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