ARM所有常用指令的實(shí)例與說(shuō)明
程序跳轉類(lèi)指令:
====================
BX,
語(yǔ)法: bx Rn
此指令執行程序跳轉,執行后,cpu從Rn這個(gè)寄存器里面所存的內存地址處開(kāi)始繼續執行。由于是跳轉,因此也會(huì )同時(shí)刷新管道線(xiàn)。另外,如果此Rn的最低位為1的話(huà),隨后的指令將被譯作thumb指令,如果最低位為0的話(huà),隨后的指令將被譯作arm32位指令。因此,此指令可以用于在32位arm指令與16位thumb指令之間進(jìn)行跳轉。
32位代碼轉入16位代碼執行:
16位代碼轉入32位代碼執行:
B, BL 指令,
語(yǔ)法: 指令 表達式/label
B指令就直接跳轉指定的地方,bl跳轉到指定的地方之前還要把當前pc保存在lr寄存器里面。
die_loop:
b die_loop這樣就構成了死循環(huán)
bl add保存當前pc到lr,然后調用add函數,
數據處理類(lèi)指令:
====================
mov, mvn指令:
語(yǔ)法: 指令 目標寄存器, 操作數
mov指令把操作數拷貝到目標寄存器里面。操作數可以是:寄存器,或者立即數表達式,
例如:
mov r0, r1# 把r1賦給r0
mov r2, #7
mov r0, r1, LSL r2把r1左移r2位后賦給r0
mov r2, #100# 把立即數100賦給r2
mvn指令把操作數按位取反之后把值賦給目標寄存器。
例如:
mov r0, r1# 表示把r1里面的值按位取反后賦給r0
cmp, cmn, teq, tst, 指令:
語(yǔ)法: 指令 寄存器, 操作數
操作數可以是:寄存器,或者立即數表達式
這四條指令都是讓后面的寄存器于操作數執行相應的操作后根據結果設定cpsr寄存器里面的相應位的值。
cmp指令把寄存器和操作數相減,根據結果設定cpsr。用于比較大小。
例如:循環(huán)100次
mov r0, #0
loop100:
add r0, r0, #1
cmp r0, #100
ble loop100
cmn指令把寄存器和操作數想加,根據結果設定cpsr。用于看兩個(gè)數只和會(huì )不會(huì )有進(jìn)位。
teq指令把寄存器和操作數進(jìn)行按位異或,根據結果設定cpsr。用于測試兩個(gè)數是否相等。
tst指令把寄存器和操作數進(jìn)行按位相與,根據結果設定cpsr。用于測試某位是否為1。
這四條指令在執行期間都只是對寄存器和操作數進(jìn)行操作,并不回寫(xiě)。
and, eor, sub, rsb, add, adc, sbc, rsc, orr, bic指令:
語(yǔ)法:指令 Rd, Rn, Op2
操作數可以是:寄存器,立即數
and 指令對Rn和Op2按位與操作之后把結果賦值給Rd.
eor 指令對Rn和Op2按位異或操作之后把結果賦值給Rd.
sub 指令對Rn和Op2進(jìn)行減操作之后把結果賦值給Rd.
rsb 指令對Op2和Rn進(jìn)行減操作之后把結果賦值給Rd.
add 指令對Rn和Op2進(jìn)行加操作之后把結果賦值給Rd.
adc 指令對Rn和Op2加操作并且加上cpsr寄存器中的C位的值之后把結果賦值給Rd.
sbc 指令執行Rn-op2-1+進(jìn)位位之后把結果賦值給Rd。
rsc 指令執行Op2-Rn-1+近位位之后把結果賦值給Rd.
orr 指令對Rn和Op2按位或操作之后把結果賦值給Rd.
bic 指令執行對Op2先按位取反之后再與Rn進(jìn)行按位與操作,之后把結果賦值給Rd,用于對Rd中的某位置0.
mrs, msr指令:
語(yǔ)法: mrs Rd,
msr
msr
msr
psr可以是cpsr, spsr, mrs用于讀取psr寄存器里面的值然后賦值給Rd.
msr用于存儲Rm寄存器里面的值進(jìn)入psr里面。
msr
mul, mla指令:
語(yǔ)法:mul Rd, Rm, Rs
mla Rd, Rm, Rs, Rn
mul指令對Rm和Rs執行乘操作之后把值賦給Rd。Rd = Rm * Rs.
mla指令對Rd和Rs執行乘操作之后并加上Rn后賦值給Rd. Rd = Rm * Rs + Rn。
mull, mlal指令:
語(yǔ)法:umull RdLo, RdHi, Rm, Rs:把Rm和Rs當作32位無(wú)符號數執行乘法操作,然后把結果的低32位賦給RdLo, 高32位賦給RdHi
umlal RdLo, RdHi, Rm, Rs:把Rm和Rs當作32位無(wú)符號數執行乘法操作,再加上由RdHi和RdLo組成的64位數,然后把結果的低32位賦給RdLo, 高32位賦給RdHi
smull RdLo, RdHi, Rm, Rs:把Rm和Rs當作32位有符號數執行乘法操作,然后把結果的低32位賦給RdLo, 高32位賦給RdHi
smlal RdLo, RdHi, Rm, Rs:把Rm和Rs當作32位有符號數執行乘法操作,再加上由RdHi和RdLo組成的64位數,然后把結果的低32位賦給RdLo, 高32位賦給RdHi
ldr, str指令:
語(yǔ)法:
ldr用于從內存中加載數據到寄存器。
str用于存儲寄存器中的數據到內存中。
例子:
.LC:
ldr r0, .LC:表示把.LC所處內存地址里面的4個(gè)字節值賦給r0(這種情況需要此命令與標簽在同一段內)
ldr r0, =.LC:表示直接把.LC所處的地址賦給r0
ldr r0, [r1] : 表示把把r1所代表的內存地址里面的值賦給r0
ldr r0, [r1, #8] : 表示r1加上8個(gè)字節代表的內存地址里面的值賦給r0
ldr r0, [r1, #8]!: 表示r1加上8個(gè)字節代表的內存地址里面的值賦給r0, 然后把r1 = r1 + 8
ldr r0, [r1], #4: 表示把r1所代表的內存地址里面的值賦給r0, 之后, r1 += 4
ldr r0, [r1, r2, LSL #2] :表示把r1+r2 * 4所代表的內存地址里面的值賦給r0
str r0, [r1, r2]: 把r1 + r2所代表的內存地址里面的值賦入r0
str r0, [r1, r2]!: 把r1 + r2所代表的內存地址里面的值賦入r0, r1 = r1 + r2
ldm, stm指令:
語(yǔ)法:
Rlist, 表示寄存器列表。比如{r0, r2, r5-r7,r9 }
{!}, 表示執行完ldm或stm之后是否對Rn進(jìn)行回寫(xiě)。
{^}, 表示恢復spsr中的值到cpsr。(一般用于返回以前模式)
寄存器列表中的數據在內存中將被存放的順序為低寄存器對應低內存地址的順序存放。
stm操作始終與所指定的棧的方向保持相同,ldm相反。stm就相當于壓棧,ldm就相當于退棧。
stm表示把寄存器的數據存入內存
ldm表示把內存中的數據加載到寄存器上。
例如:
ldmfdsp, {r0,r1,r2} 表示把sp所指的內存地址開(kāi)始的12個(gè)字節分別賦值給r0,r1,r2。
ldmfdsp!, {r0,r1,r2} 表示把sp所指的內存地址開(kāi)始的12個(gè)字節分別賦值給r0,r1,r2,之后sp = sp + 12
ldmfd sp!, {r15}^表示把sp棧所指的4個(gè)字節里面的值賦給r15, 同時(shí)把spsr賦值給cpsr,并且sp += 4
stmfd sp, {r0, r1, r2} 表示把r2,r1,r0按照sp所指地址遞減存儲。也就相當于下面3條指令:
str r2, [sp, #-4]
str r1, [sp, #-8]
str r0, [sp, #-12]
stmfd sp!, {r0, r1, r2} 表示把r2,r1,r0按照sp所指地址遞減存儲。并且把sp = sp - 12,也就相當于下面4條指令:
str r2, [sp, #-4]
str r1, [sp, #-8]
str r0, [sp, #-12]
sub sp, sp, #12
特殊用法:
stmfd sp!, {r0-r15}^ : 表示把用戶(hù)模式下面的r0-r15寄存器存在當前模式下面的sp所指向的棧中。
stmfd sp!, {r0-r14}^ : 表示把用戶(hù)模式下面的r0-r14寄存器存在當前模式下面的sp所指向的棧中。用于進(jìn)程切換的時(shí)候保存用戶(hù)模式下面的寄存器。
ldmfd sp!, {r0-r14}^ : 寄存器列表這里面不帶有r15(pc), 表示把當前模式下面sp所指的棧中的15個(gè)int拷貝用戶(hù)模式下面的r0-r14。這個(gè)用于恢復進(jìn)程狀態(tài)。
swp指令:
語(yǔ)法:
swp指令執行單字節或單字的內存于寄存器的數據交換原子操作。把rn所指內存里面的值賦值給Rd, 然后把R1存入R2所指的內存。經(jīng)常用于內核中實(shí)現控制互斥與信號等功能。
例如:
swp r0, r1,[r2]:表示把r2所指的內存地址里面的值賦值給r0, 然后把r1存入r2所指內存地址。相當于下面2條指令的原子操作。
ldr r0, [r2]
str r1, [r2]
評論