bl 和 ldr跳轉程序的區別

首先說明

BL main 爲相對跳轉指令,與位置無關代碼。

LDR PC,=main 爲絕對跳轉指令,與位置有關代碼。

可能看到這的人都有疑問,如下圖。鏈接地址爲0x50000000。

兩段代碼main函數位置如下圖:


左右圖的第11行 左邊是 bl main的反彙編爲 “ bl 50000298 ”,右邊是 ldr pc,=main的反彙編爲 " ldr pc,[pc, #4] "

乍一看第一個 bl 50000298 不是直接跳轉到 50000298麼,那不就是絕對跳轉? ,第二個使用 ldr pc,[pc, #4],使用的時pc偏移量不是相對跳轉麼?

那你就中記了。

arm-linux-objdump的反彙編太貼心了。

左邊圖:

              反彙編軟件在反彙編的時候把你的bl mian這條語句中的main的地址幫你計算了出來。但是,,它並不是按照你的實際運行地址計算的而是按照你的鏈接地址來的,

所以就出現了bl 50000298;正如左邊圖示的main函數位置。

右邊圖:

            ldr pc, =main這條指令爲僞指令,編譯的時候會將main的鏈接地址存入一個地址。再將 ldr pc, =main轉化爲 ldr pc, [ pc, offset ]這樣一個指令。所以上面的反匯編出來的 ldr pc, =main 就變成了 ldr pc. [ pc, #4 ],這句代碼相當於  pc = *(pc+4); 由於ARM使用了流水線的原因,所以在執行 ldr pc. [ pc, #4 ]的時候 pc 不在這句代碼這裏了,而是跑到了 pc+8的地方,而 pc = *(pc + 4) = 5000029c 注意!!!!!!!! 這裏的   5000029c  是存在代碼段中的一個常量,並不是計算出來的,不會隨程序的位置而改變,所以無論代碼和pc怎麼變 *(pc+4) 的值時不會變的。

到這還是不明白爲什麼bl main是相對跳轉 ,ldr pc, =main是絕對跳轉,反而是兩個指令都是絕對跳轉了。

上面說了,反彙編軟件在反彙編BL main時幫我們把main的地址算出來了,,那我們看看它時怎麼算的,,,,,,費了好大力氣終於找到了BL跳轉指令的計算方法(大神見笑了),看圖:(該圖取至 《ARM體系結構與編程》--- 杜春雷 Page 59)


此時我們來模擬一下反彙編軟件的計算過程:(爲方便理解我們假設程序在 50000000處執行)

           看一下左圖 50000010 處的機器碼爲 eb0000a0 轉化成二進制就是 1110 1011 0000 0000 0000 0000 1010 0000

最高4位時條件碼 1110 就是無條件執行 (《ARM體系結構與編程》 Page 23)。

接着的4位 1011 是BL指令的指令碼。

後面的24位0000 0000 0000 0000 1010 0000 即爲地址碼 

按照其計算方式:

     1、將指令中24位帶符號的補碼立即數擴展爲32位(擴展其符號位)

            原數變成  0000 0000 0000 0000 0000 0000 1010 0000

     2、將此數左移兩位

            變成    0000 0000 0000 0000 0000 0010 1000 0000 =  0x280

     3、將得到的值加到PC寄存器中得到目標地址

           由於ARM流水線原因 此時的 pc = 0x50000010+8 = 0x50000018

           pc = pc + 0x280 = 0x50000298與左邊圖中的mian的地址相等。程序就跳轉到了mian

在算的過程中我們使用的始終是PC的值,假設程序在 0 地址處執行,那麼計算方法一樣,pc 的值變了計算出來的結果也隨之改變。所以 BL 的跳轉時與位置無關的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章