新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM匯編和內(nèi)嵌匯編

ARM匯編和內(nèi)嵌匯編

作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
一、ldr的確是個復(fù)雜的指令,現(xiàn)總結(jié)一下:

首先要判斷我們用的是ldr arm指令還是偽指令。 當(dāng)我們用的是arm指令時,它的作用不是向寄存器里加載立即數(shù),而是將某個地址里 的內(nèi)容加載到寄存器。而偽指令ldr的作用就是向寄存器里加載立即數(shù)。
(1) ldr偽指令
ldr偽指令的格式是 ldr Rn, =expr
其中,expr是要加載到Rn中的內(nèi)容,一般可以是立即數(shù)或者label。
如果expr可以用8bit數(shù)據(jù)向右移偶數(shù)位得到,那么這條偽指令就被編譯器翻譯成mov指令。具體的移位情況可以去查閱資料。反之如果立即數(shù)很大,超過了12bit的表示范疇,那么就不能用一條mov指令了,畢竟arm指令最大只有32bit的空間可用(RISC的arm所有的指令長度是一致的,效率較高,當(dāng)然我們并不關(guān)心16bit的thumb指令)。如果不能用一條32bit的指令乘下來,那么就只能另辟蹊徑了,新開一段緩沖,將立即數(shù)expr放到里面,然后將其地址(暫時標記為addr)拿來使用:
ldr Rn, addr
xxx (xxx就是expr)
xxx

由于編譯器一般來說新安排的存儲這個立即數(shù)expr的緩沖的位置是在相應(yīng)代碼的附近(這個應(yīng)該可以控制,好像是使用.ltorg偽指令)。我們從addr地址加載數(shù)據(jù)到Rn不就可以了。

(2)ldr arm 指令
就是將一個地址的內(nèi)容加載到寄存器。不能用mov,因為arm里的mov只是在寄存器之間傳輸數(shù)據(jù),不支持在寄出器和memory之間傳遞數(shù)據(jù)。因此就出現(xiàn)了ldr/str指令。如ldr Rn, addr,注意這里的addr的值也是有限制的。這個label應(yīng)該距離當(dāng)前指令的距離不超過4k。因為我們知道label在具體使用的時候應(yīng)該是被翻譯成了相對偏移,如果這個label長度不超過12bit,那么就不應(yīng)超過4k,我們可以這樣做:
ldr pc, _start_armboot
_start_armboot: .word arm_startboot
這樣label _start_armboot就在指令下方,因此肯定是合法的。

本文引用地址:http://m.butianyuan.cn/article/201611/318797.htm

ldr r0, [r1, #4] 的含義就是把r1+4 這個地址處的DOWRD 加載到r0,而尋址后,r1 的內(nèi)容并不改變。

ldr r0, [r1, #4]! 這種變址方式有點類似于++i的含義,尋址前先對基地址寄存器進行運算,然后尋址. 其基本的語法是在尋址符[]后面加上一個"!" 來表示

二、.world

說說這個 .word 的作用。

word expression 就是在當(dāng)前位置放一個 word 型的值,這個值就是expression
舉例來說,
_rWTCON:
.word 0x15300000

就是在當(dāng)前地址,即 _rWTCON 處放一個值0x15300000
不是把地址0x1530 0000 上的內(nèi)容傳遞到r1,是把地址_rWTCON上的內(nèi)容放到r1,而地址_rWTCON上的內(nèi)容是0x15300000。實際上就是把r1設(shè)置為0x15300000

三 bic

BIC(位清除)指令對 Rn 中的值 和 Operand2 值的反碼按位進行邏輯“與”運算。 (注意:ARM官方網(wǎng)站有誤, 寫的是補碼)
BIC 是 邏輯”與非” 指令, 實現(xiàn)的 Bit Clear的功能

舉例:
BIC R0, R0 , #0xF0000000
#將 R0 高4位清零

BIC R1, R1, #0x0F
#將R1 低4位清0
RSB 反向減法
Rn, Operand2
RSB(反向減法)指令可從 Operand2 中的值減去 Rn 中的值。
這是很有用的,因為有了該指令,Operand2 的選項范圍就會更大。

例如:
RSB r4, r4, #1280
從1280中減去 R4

RSB R4, R0, #0×46
從0×46 中 減去 R0, 放入R4

四、ADR

ADR的定義為:小范圍的地址讀取偽指令,ADR指令將基于PC相對偏移的地址值讀取到寄存器中,在編譯源程序時ADR偽指令被編譯器 替換成一條合適的指令。通常,編譯器用一條ADD指令或SUB指令來實現(xiàn)該ADR偽指令的功能,若不能用一條指令實現(xiàn),剛產(chǎn)生錯誤。

在如上的定義中,有兩個關(guān)鍵信息:⑴將基于PC相對偏移的地址值讀取到寄存器中;⑵被編譯器替換成一條合適的指令。ADR指令只能將地址值讀取到寄存器中,而不能是其它的立即數(shù),并用只能用一條指令。

如果在匯編程序中使用ADR R1,ResetHandel語句,其中ResetHandel是匯編程序中的一個標簽,此條偽指令的作用是把ResetHandel標簽所在的指令地址 讀取到寄存器R0中

根據(jù)上面的分析,可以看到,編譯器在編譯的時候把ADR偽指令編譯成一個ADD R1,PC,Immediate指令,其中Immediate是一個立即數(shù),數(shù)值是ResetHandel語句和此條偽指令之間的差值,由編譯器自動算 出。由于立即數(shù)尋址的約束,這個Immediate存在一定的約束,所以會出現(xiàn)定義中所說的不能用一條指令實現(xiàn)。

五、ldmia 和 stmia

所有的示例指令執(zhí)行前:
mem32[0x1000C] = 0x04
mem32[0x10008] = 0x03
mem32[0x10004] = 0x02
mem32[0x10000] = 0x01
r0 = 0x00010010
r1 = 0x00000000
r3 = 0x00000000
r4 = 0x00000000
1) ldmia r0!, {r1-r3} 2) ldmib r0!, {r1-r3}
執(zhí)行后: 執(zhí)行后:
r0 = 0x0010001C r0 = 0x0010001C
r1 = 0x01 r1 = 0x02
r2 = 0x02 r2 = 0x03
r3 = 0x03 r3 = 0x04
至于DA 和DB 的模式,和IA / IB 是類似的,不多說了。
最后要說的是,使用ldm 和stm指令對進行寄存器組的保護是很常見和有效的功能。配對方案:
stmia / ldmdb
stmib / ldmda
stmda / ldmib
stmdb / ldmia
繼續(xù)來看兩個例子:
執(zhí)行前:
r0 = 0x00001000
r1 = 0x00000003
r2 = 0x00000002
r3 = 0x00000001
執(zhí)行的指令:
stmib r0!, {r1-r3}
mov r1, #1 ; These regs have been modified
mov r2, #2
mov r3, #3
當(dāng)前寄存器狀態(tài):
r0 = 0x0000100C
r1 = 0x00000001
r2 = 0x00000002
r3 = 0x00000003
ldmia r0!, {r1-r3}
最后的結(jié)果:
r0 = 0x00001000
r1 = 0x00000003
r2 = 0x00000002
r3 = 0x00000001
另外,我們還可以利用這個指令對完成內(nèi)存塊的高效copy:
loop
ldmia r9!, {r0-r7}
stmia r10!, {r0-r7}
cmp r9, r11
bne loop

六、CMP

CMP指令的格式為:
CMP{條件} 操作數(shù)1,操作數(shù)2
CMP指令用于把一個寄存器的內(nèi)容和另一個寄存器的內(nèi)容或立即數(shù)進行比較,同時更新CPSR中條件標志位的值。該指令進行一次減法運算,但不存儲結(jié)果,只 更改條件標志位。標志位表示的是操作數(shù)1與操作數(shù)2的關(guān)系(大、小、相等),例如,當(dāng)操作數(shù)1大于操作操作數(shù)2,則此后的有GT 后綴的指令將可以執(zhí)行。
指令示例:
CMP R1,R0 ;將寄存器R1的值與寄存器R0的值相減,并根據(jù)結(jié)果設(shè)置CPSR的標志位
CMP R1,#100 ;將寄存器R1的值與立即數(shù)100相減,并根據(jù)結(jié)果設(shè)置CPSR的標志位

cmp r0, #0
beq 1f ; 如果r0==0那么向前跳轉(zhuǎn)到B處執(zhí)行
bne 1b ; 否則向后跳轉(zhuǎn)到A處執(zhí)行1: ;
1b,1f里的b和f表示backward和forward,1表示局部標簽1

TST R0, #0X8
BNE SuspendUp ;BNE指令是“不相等(或不為0)跳轉(zhuǎn)指令”:

LDR R1,#0x00000000

先進行and運算,如果R0的第四位不為1,則結(jié)果為零,則設(shè)置zero=1(繼續(xù)下面的LDR指令);

否則,zero=0(跳到SuspendUp處執(zhí)行)



關(guān)鍵詞: ARM匯編內(nèi)嵌匯

評論


技術(shù)專區(qū)

關(guān)閉