ARM中的ADR ADRL LDR
LDR偽指令的形式是“LDR Rn,=expr”。下面舉一個(gè)例子來(lái)說(shuō)明它的用法。 COUNT EQU 0x40003100 …… LDR R1,=COUNT MOV R0,#0 STR R0,[R1] COUNT是我們定義的一個(gè)變量,地址為0x40003100。這中定義方法在匯編語(yǔ)言中是很常見的,如果使用過(guò)單片機(jī)的話,應(yīng)該都熟悉這種用法。 LDR R1,=COUNT是將COUNT這個(gè)變量的地址,也就是0x40003100放到R1中。 MOV R0,#0是將立即數(shù)0放到R0中。最后一句STR R0,[R1]是一個(gè)典型的存儲(chǔ)指令,將R0中的值放到以R1中的值為地址的存儲(chǔ)單元去。實(shí)際就是將0放到地址為0x40003100的存儲(chǔ)單元中去。可見這三條指令是為了完成對(duì)變量COUNT賦值。用三條指令來(lái)完成對(duì)一個(gè)變量的賦值,看起來(lái)有點(diǎn)不太舒服。這可能跟ARM的采用RISC有關(guān)。 下面還有一個(gè)例子 ;將COUNT的值賦給R0 LDR R1,=COUNT LDR R0,[R1] LDR R1,=COUNT這條偽指令,是怎樣完成將COUNT的地址賦給R1,有興趣的可以看它編譯后的結(jié)果。這條指令實(shí)際上會(huì)編譯成一條LDR指令和一條 DCD偽指令。
本文引用地址:http://m.butianyuan.cn/article/201611/317542.htm請(qǐng)問(wèn)ARM指令LDR和ARM偽指令LDR有什么區(qū)別
偽指令LDR{cond} register, ={expr|label-expr}
expr為32為常量。編譯器根據(jù)expr的取值情況來(lái)處理這條偽指令:
1、當(dāng)expr表示的地址沒(méi)有超過(guò)mov或mvn指令中地址的取值范圍時(shí),編譯器用合適的mov指令或mvn指令代替該LDR偽指令。
2、當(dāng)expr表示的地址超過(guò)了mov或mvn指令中地址的取值范圍時(shí),編譯器將該常數(shù)放在緩沖區(qū)中,同時(shí)用一條基于PC的LDR指令讀取該常數(shù)。
...............................
通過(guò)上面兩種可以得出偽指令LDR和ARM指令LDR的區(qū)別,具體使用時(shí),可以不用考慮二者的區(qū)別,由編譯器決定的,看源碼時(shí),你只要搞清楚它的功能就行。
第一個(gè)就是把0xf830這個(gè)值放到r2中去,第二個(gè)和第三個(gè)的意義也是一樣的。最后一條指令應(yīng)該是錯(cuò)誤的。
由于arm是risc精簡(jiǎn)指令集,指令都是32位的,在編碼中操作碼,目標(biāo)和源寄存器是要占掉32位一部分,所以一條指令里面不可能存一個(gè)32位的立即數(shù),所以arm提供了一條偽指令來(lái)完成一條指令load一個(gè)32位的立即數(shù)。方法是在這條指令附近放要load的值,再利用當(dāng)前的pc+偏移load這個(gè)數(shù),注意ldr的原來(lái)的意義是將內(nèi)存的某個(gè)值load到寄存器里面。
比如:
ldr r0, =0x5000010
經(jīng)過(guò)arm的assembler的翻譯實(shí)際上就是:
ldr r0, [pc+#0x4] ;;指令是4byte 32位,就是將內(nèi)存中下一個(gè)word放到r0中
0x500010 ;;這個(gè)地方放的是數(shù)值
這里,0x4是在它立即數(shù)的范圍內(nèi)的
具體的看看文檔,ads的pdf目錄下有一個(gè)AssemblerGuide
arm指令中mov和ldr的區(qū)別
ARM是RISC結(jié)構(gòu),數(shù)據(jù)從內(nèi)存到CPU之間的移動(dòng)只能通過(guò)L/S指令來(lái)完成,也就是ldr/str指令。
比如想把數(shù)據(jù)從內(nèi)存中某處讀取到寄存器中,只能使用ldr
比如:
ldr r0, 0x12345678
就是把0x12345678這個(gè)地址中的值存放到r0中。
而mov不能干這個(gè)活,mov只能在寄存器之間移動(dòng)數(shù)據(jù),或者把立即數(shù)移動(dòng)到寄存器中,這個(gè)和x86這種CISC架構(gòu)的芯片區(qū)別最大的地方。
x86中沒(méi)有l(wèi)dr這種指令,因?yàn)閤86的mov指令可以將數(shù)據(jù)從內(nèi)存中移動(dòng)到寄存器中。
另外還有一個(gè)就是ldr偽指令,雖然ldr偽指令和ARM的ldr指令很像,但是作用不太一樣。ldr偽指令可以在立即數(shù)前加上=,以表示把一個(gè)地址寫到某寄存器中,比如:
ldr r0, =0x12345678
這樣,就把0x12345678這個(gè)地址寫到r0中了。所以,ldr偽指令和mov是比較相似的。只不過(guò)mov指令限制了立即數(shù)的長(zhǎng)度為8位,也就是不能超過(guò)512。而ldr偽指令沒(méi)有這個(gè)限制。如果使用ldr偽指令時(shí),后面跟的立即數(shù)沒(méi)有超過(guò)8位,那么在實(shí)際匯編的時(shí)候該ldr偽指令是被轉(zhuǎn)換為mov指令的。
ldr偽指令和ldr指令不是一個(gè)同東西。
LDR R1,=COUNT
MOV R0,#0
STR R0,[R1]
COUNT是我們定義的一個(gè)變量,地址為0x40003100。這中定義方法在匯編語(yǔ)言中是很常見的,如果使用過(guò)單片機(jī)的話,應(yīng)該都熟悉這種用法。
LDR R1,=COUNT是將COUNT這個(gè)變量的地址,也就是0x40003100放到R1中。
MOV R0,#0是將立即數(shù)0放到R0中。最后一句STR R0,[R1]是一個(gè)典型的存儲(chǔ)指令,將R0中的值放到以R1中的值為地址的存儲(chǔ)單元去。實(shí)際就是將0放到地址為0x40003100的存儲(chǔ)單元中去。可見這三條指令是為了完成對(duì)變量COUNT賦值。用三條指令來(lái)完成對(duì)一個(gè)變量的賦值,看起來(lái)有點(diǎn)不太舒服。這可能跟ARM的采用RISC有關(guān)。
ARM偽指令之地址讀?。?strong>ADR ADRL LDR
1、ADR偽指令--- 小范圍的地址讀取
ADR偽指令將基于PC相對(duì)偏移的地址值或基于寄存器相對(duì)偏移的地址值讀取到寄存器中。在匯編編譯器編譯源程序時(shí),ADR偽指令被編譯器替換成一條合適的指令。通常,編譯器用一條ADD指令或SUB指令來(lái)實(shí)現(xiàn)該ADR偽指令的功能,若不能用一條指令實(shí)現(xiàn),則產(chǎn)生錯(cuò)誤,編譯失敗。
ADR偽指令格式 :ADR{cond} register, expr
地址表達(dá)式expr的取值范圍:
當(dāng)?shù)刂分凳亲止?jié)對(duì)齊時(shí),其取指范圍為: +255 ~ 255B;
當(dāng)?shù)刂分凳亲謱?duì)齊時(shí),其取指范圍為: -1020 ~ 1020B;
2、ADRL偽指令----中等范圍的地址讀取
ADRL偽指令將基于PC相對(duì)偏移的地址值或基于寄存器相對(duì)偏移的地址值讀取到寄存器中,比ADR偽指令可以讀取更大范圍的地址。在匯編編譯器編譯源程序時(shí),ADRL偽指令被編譯器替換成兩條合適的指令。若不能用兩條指令實(shí)現(xiàn),則產(chǎn)生錯(cuò)誤,編譯失敗。
ADRL偽指令格式:ADRL{cond} register, expr
地址表達(dá)式expr的取值范圍:
當(dāng)?shù)刂分凳亲止?jié)對(duì)齊時(shí),其取指范圍為: -64K~64K;
當(dāng)?shù)刂分凳亲謱?duì)齊時(shí),其取指范圍為: -256K~256K;
3、LDR偽指令-----大范圍的地址讀取
LDR 偽指令用于加載32位的立即數(shù)或一個(gè)地址值到指定寄存器。在匯編編譯源程序時(shí),LDR偽指令被編譯器替換成一條合適的指令。若加載的常數(shù)未超出MOV或 MVN的范圍,則使用MOV或MVN指令代替該LDR偽指令,否則匯編器將常量放入文字池,并使用一條程序相對(duì)偏移的LDR指令從文字池讀出常量。
評(píng)論