首先來看一段指令和它的彙編結果:
area test,code,readonly
entry
ldr r0,_start
adr r0,_start
ldr r0,=_start
nop_start
nopend
彙編結果如下圖:
首先,當執行第一條指令時,pc的指向是0x8008
_start的值是0x8010,相差為8,所以,ldr指令是將通過這個差值來尋找,載入的是資料,不是位址值。
執行第二條指令時,pc指向0x800c,跟_start指令相差為4,所以這個adr指令也是通過差值來尋找。
r0=當前pc值加上(算出來的當前pc值和_start位址之間的差值)
當前pc值和_start位址之間的差值是已經確定的,當程式執行在不同的位址上,這個r0會隨之發生變化,但是
最終都會正確找到這個_start的位址值。
進行第三條指令分析之前,先來看一下偽指令,ldr r0,=start
這條指令在編譯的時候,會佔兩條指令的空間,因為通常ldr載入的不是乙個立即數,超出立即數的範圍,所以需要另外的32bit空間來儲存這個資料。
我們來看一下這條指令的編譯結果:
ldr r0 ,[pc,#0x0004]
(即使pc發生變化,只要使得pc+04這個位址中的資料,也就是r0實際的值,也就是_start的值確定下來,那麼r0就不會發生變化)
是這個位址中儲存的資料就是_start的位址,
首先,看一下當前的pc值是0x8010,加上4之後為0x8014,而在0x8014位置中儲存的是0x8010這個資料
而0x8010這個資料就是_start的數值,所以,可以說0x8014這個位址中儲存的就是_start這個資料,也就是ldr偽指令
這也就是說無論pc執行在哪個位址空間,ldr中的r0的值永遠不會發生變化。
文字池所佔得第二個空間位址。
第一點注意:pc值比當前執行指令值大8
第二點注意:實際上,ldr r0,=_start可以轉化為:
ldr rn, [pc, #offset to literal pool] 的形式,直接去文字池所在的位址去找到這個位址。
且對於ldr偽指令,這個偏移範圍在arm狀態下<4kb,且這個偏移的方向可以向前可以向後
在thumb狀態下,這個偏移範圍<1kb,且只能向前偏移。
第三點注意:adr指令通常轉化為乙個add或者sub指令
可以載入的偏移位址的範圍
在字對齊的情況下,是不超過+-255bytes,在非字對齊的情況下是不超過+-1020bytes
這裡要求的都是字對齊,arm中字是32位。
而對於adrl指令,它的跳轉範圍更大一點:
當字不對其的情況下是+-64kb,當字對齊的情況下是+-256kb,且沒有在thumb情況下使用
理解adr,ldr指令
在閱讀u bootstart.s時,對adr和ldr指令有些疑惑,經韋老師指點,在參閱了一些網上的博文後,做了這個實驗 參照韋老師的 和makefile寫了 test adr.s text globl start start ldr r0,test adr r0,test ldr r0,test n...
指令和偽指令的區別
這個標題看似簡單,但是我卻一下子沒明白,這裡做下記錄。指令 每一條指令語句在源程式彙編時都要產生可供計算機執行的指令 即目標 所以這種語句又叫做可執行語句,每一條指令語句表示cpu具有的乙個基本能力,比如資料傳送,兩數相加或相減,移位等,而這種能力是在目標程式執行時完成的,是依賴於cpu 儲存器 i...
ARM指令和THUMB指令的區別
arm處理器的工作狀態 在arm的體系結構中,可以工作在三種不同的狀態,一是arm狀態,二是thumb狀態及thumb 2狀態,三是除錯狀態。嵌入式系統開發與應用教程 第2版 上介紹說 有兩種狀態arm狀態和thumb狀態,當時初學甚為不解,現在一知半解時再看忽然想到了顯示中的例子 arm核就好比乙...