ARM之重定位和鏈結指令碼

2021-08-19 22:58:12 字數 2574 閱讀 7170

一、重定位

1、靜態重定位:靜態重定位是在程式執行之前進行重定位,它根據裝配模組將要裝入的記憶體起始

位置,直接修改裝配模組的有關使用位址的指令。

切地說,是在每次訪問記憶體單元前才進行位址變換。動態重定位可是裝配模組不加任何修改而裝入內

存,但是它需要硬體-定位暫存器的指出。

3、為什麼需要重定位?

我們知道**分為:位置無關碼和位置有關碼。位置無關碼在哪個位址上面執行效果都一樣的,但是位置有

關碼就必須在規定的位址處執行才可以。這個規定的位址就是鏈結位址,而我們**執行時候的位址是運

行位址,位置有關**要求鏈結位址和執行位址必須一致

。但由於某些原因(例如:我們在用裸機時,我的

行執行,所以就用到了重定位。

4、程式中的bss段,data段,**段(.text),堆(heap),棧(stack)

.bss段:程式中未初始化的和已經初始化為0的全域性變數和已經初始化為0的靜態區域性變數(static)

.data段:程式中已經初始化非零的全域性變數和已經初始化的非零的靜態區域性變數(static)

**段:用來存放**的地方(.text段),不可修改,存放在唯讀區域內

堆:程式設計師自己申請的記憶體區域,也就是malloc()函式申請的記憶體區域,用free()函式來釋放的區域

棧:存放區域性變數的區域,函式中的區域性變數都是存放棧中

5、鏈結指令碼

link.lds為鏈結指令碼的名字

sections

.data :

bss_start = .;       //把當前的位址賦值給bss_start

.bss :

bss_end = .;       //把當前的位址賦值給bss_end

}

6、重定位的具體實現

// adr指令用於載入_start當前執行位址

adr r0, _start // adr載入時就叫短載入

ldr r1, =_start     // ldr載入時如果目標暫存器是pc就叫長跳轉,如果目標暫存器是r1等就叫長載入

// bss段的起始位址

ldr r2, =bss_start // 就是我們重定位**的結束位址,重定位只需重定位**段和資料段即可

cmp r0, r1 // 比較_start的執行時位址和鏈結位址是否相等

beq clean_bss // 如果相等說明不需要重定位,所以跳過copy_loop,直接到clean_bss

// 如果不相等說明需要重定位,那麼直接執行下面的copy_loop進行重定位

// 重定位完成後繼續執行clean_bss。

// 用彙編來實現的乙個while迴圈

copy_loop:

ldr r3, [r0], #4 // 源,後面的#4就是:位址在不斷的加4

str r3, [r1], #4 // 目的 這兩句**就完成了4個位元組內容的拷貝

cmp r1, r2 // r1和r2都是用ldr載入的,都是鏈結位址,所以r1不斷+4總能等於r2

bne copy_loop

// 清bss段,其實就是在鏈結位址處把bss段全部清零

clean_bss:

ldr r0, =bss_start

ldr r1, =bss_end

cmp r0, r1 // 如果r0等於r1,說明bss段為空,直接下去

beq run_on_dram // 清除bss完之後的位址

mov r2, #0

clear_loop:

str r2, [r0], #4 // 先將r2中的值放入r0所指向的記憶體位址(r0中的值作為記憶體位址),

cmp r0, r1 // 然後r0 = r0 + 4

bne clear_loop

run_on_dram:

// 長跳轉到led_blink開始第二階段

ldr pc, =led_blink // ldr指令實現長跳轉和bl是短載入

//最後這裡跳轉,是跳轉到重定位的**所對應的led_blink這個函式那裡去執行的

// 彙編最後的這個死迴圈不能丟

b .

(1)、把整段**搬用過重定位的記憶體**(用copy_loop來實現)

(2)、清bss段(clean_bss)來實現

(3)、跳轉到重定位的那段記憶體去執行(run_on_dram來實現)

歡迎各位指出不足之處

重定位和鏈結指令碼

重定位實際就是在執行位址處執行一段位置無關碼pic,讓這段pic 也就是重定位 從執行位址處把整個程式映象拷貝乙份到鏈結位址處,完了之後使用一句長跳轉指令從執行位址處直接跳轉到鏈結位址處去執行同乙個函式,這樣就實現了重定位之後的無縫連線。鏈結位址 鏈結時指定的位址 指定方式為 makefile中用 ...

重定位和鏈結指令碼

但是也有一種特別的指令他可以跟指定的鏈結位址沒有關係,這些 不管放在 都可以正常執行。分析 在linux中的應用程式 gcc hello.c o hello bootloader必須大於16kb小於96kb,假定為80kb。啟動過程如下 開機上電後bl0執行,bl0載入外部啟動裝置中的bootloa...

重定位引入和鏈結指令碼

1 乙個事實 大部分指令是位置有關編碼 位置無關編碼 pic,position independent code 彙編原始檔被編碼成二進位制可執行程式時編碼方式與位置 記憶體位址 無關。位置有關編碼 彙編原始碼編碼成二進位制可執行程式後和記憶體位址是有關的。我們在設計乙個程式時,會給這個程式指定乙個...