ARM指令格式
ARM指令格式解析
opcode: 指令助記符,例如,MOV ,ADD,SUB等等
cond:指令條件碼表.下面附一張圖
{S}:是否影響CPSR的值.
{.W .N}:指令寬度說明符,無論是ARM代碼還是Thumb(armv6t2或更高版本)代碼都可以在其中使用.W寬度說明符,但它對32位的代碼沒有影響。如果要將指令匯編為16位編碼,則可以為指令加上.N寬度說明符。
Rd:目的寄存器.
Rn:第一個操作數寄存器.
operand2:第二個操作數,第二個操作數可以是寄存器,立即數,或者是寄存器移位操作.
跳轉指令
B指令
B {cond} lable
B指令執行時,如果條件滿足,就直接跳轉到label指定的地址繼續執行.
例如:BNE 就是not equal z=0時候,跳轉到label執行
BL指令
B {cond} lable
BL是指帶鏈接的跳轉指令,如果條件cond滿足,會將當前指令的下一條指令的地址copy到R14(LR)寄存器中,然后跳轉到lable指定的地址繼續執行,這條指令通常作用于子程序,在子程序的尾部 執行MOV PC,LR 就可以返回到主程序中,繼續執行下一條指令。
BX指令
BX{cond}Rm
就是跳轉時候判斷是用arm代碼還是Thumb代碼執行
存儲器訪問指令
存儲器訪問操作包括從存儲器中加載數據、或者存數據到存儲器、再或者是存儲器與寄存器之間的數據交換.
LDR指令
LDR用于從存儲器中加載數據到寄存器中格式
LDR{type}{cond}Rd,lable
LDRD{cond}Rd,Rd2,lable
type指明了操作數據的大小,他的取值
cond:仍為執行條件和上面的一樣
Rd:是要加載的寄存器
lable:Lable 為要讀取的內存地址 有三種表示方法
直接偏移量
如: LDR R8, [R9, #04] 、LDR R8, [R9], #04
寄存器偏移
如: 直 接 偏 移 量。 如: LDR R8, [R9, #04] 、LDR R8, [R9], #04
相對PC偏移
如: LDR R8, label1
STR指令
STR用于存儲內容到指定的內存地址中
STR{ type}{ cond} Rd, label
STRD{ cond} Rd, Rd2, label
指令格式基本和LDR相同,只是type中的SB與SH對STR無效。
指令舉例:STR R0,[R2,#04] 將R0寄存器的數據,存儲到R2+4所指向的存儲單元中去
LDM指令
LDM可以從指定的存儲單元加載多個數據到一個寄存器列表,他的格式如下:
LDM{ addr_mode}{ cond} Rn{!} reglist
addr_mode的取值
Rn:基地址寄存器,用于存儲初始地址
!:為可選后綴.如果有! 那么最終地址將寫回到Rn寄存器
reglist:寄存器列表,用大括號括起來,多個連續的寄存器使用'-'連接,如{R0-R3}如果寄存器不是連續的,則使用逗號將他們分隔開來,如{R0,R1,R7}
指令舉例:LDM R0! {R1-R3} 依次加載R0指向的存儲單元的數據,到R1,R2,R3寄存器中
STM指令
STM指令將一個寄存器列表的數據存儲到指定的存儲單元。它的格式如下:
STM{addr_mode}{cond}Rn{!} reglist
STM與LDM的格式是一樣的,STM指令:
STM R1!,{R3-R6,R11} 將R3-R6 R11 寄存器存儲的內容存到R1所指向的存儲單元中
STM SP!,{R3-R7}
PUSH指令
PUSH將寄存器推入滿遞減堆棧,它的格式如下
PUSH{cond} reglist
指令舉例:PUSH {r0,r4-r7} 將R0,R4-R7寄存器內容壓入堆棧
POP指令
POP從滿遞減堆棧中彈出數據到寄存器
POP{cond} reglist
POP {r0,r4-r7} 將R0,R4,R5,R6,R7從堆棧中彈出
SWP指令
SWP用于寄存器與存儲器之間的數據交換,他的格式如下
SWP {B}{cond}Rd,Rm,[Rn]
B:是可選的字節,若有B,則交換字節,否則交換32位的字。
cond:和前面一樣是條件
Rd:為要從存儲器中加載數據的寄存器 存儲器->寄存器
Rm:為要從寄存器加載數據到存儲器的寄存器 寄存器->存儲器
Rn:為需要進行數據交換的存儲器地址。Rn不能與Rd和Rm相同
如果Rd與Rm相同,可實現單個寄存器與存儲器的數據交換。例如:
SWP R1,R1,[R0] 將R1寄存器與R0寄存器指向的存儲單元中的內容進行交換
SWP R1,R2,[R0] 將R0寄存器指向的存儲單元的內容取出,存入R1寄存器,再將R2寄存器存儲的內容存儲到R0寄存器所指向的內存單元
數據處理指令
數據指令主要用于寄存器之間的數據傳送
MOV指令
MOV的功能是將8位立即數或者寄存器的內容傳送到目標寄存器,指令格式如下
MOV{cond}{S}Rd,operand2
MOV指令舉例
MOV,RO,#8 == R0 = 8
MOV,RO,R1 == R0 = R1
MVN指令
MVN為數據非傳送指令,它的功能是將8位的立即數或寄存器按位取反后,傳送到目標寄存器中。指令格式如下:
MVN{cond}{S}Rd,operand2
MVN R0,#0xFF == R0=0xFFFFFF00
算數運算指令
ADD指令
ADD為加法指令
指令格式: ADD{cond}{S}Rd,Rn,operand2
指令舉例:
ADD R0,R1,#2 R0 = R1+@
ADDS R0,R1,R2 R0 = R1+R2 影響標志位
ADD R0,R1,LSL #3 R0 = R1 * 8
ADC指令
指令格式: ADC{cond}{S}Rd,Rn,operand2
ADC為帶進位的加法指令,他的功能是將Rn,operand2的值相加,然后再加上CPSR寄存器的C條件標志位的值,最后將結果保存到Rd寄存器.
指令舉例: ADD R0,R0,R2 ADC R1,R1,R3
SUB指令
指令格式: SUB{cond}{S}Rd,rn,operand2
SUB為減法指令,他的功能是將Rn與operand2的值
指令舉例:
SUB RO,R1,#4 R0 = R1-4
同理帶S的影響標志位
RSB
指令格式:RSB{cond}{S}Rd,Rn,operand2
RSB是逆向減法指令,就是說用operand2 - Rn 然后賦值給Rd
指令舉例
RSB R0,R1 #0X1234
邏輯運算
邏輯運算指令主要完成與、或、異或、移位等邏輯運算操作
AND指令
邏輯 "與" 指令
指令格式:AND{cond}{S}Rd,Rn,operand2
指令舉例:AND RO,R0,#1 用來測試R0的最低位
ORR指令
邏輯 "或" 指令
指令格式: ORR{cond}{S}Rd,Rn,operand2
指令舉例:ORR R0,RO,#0X0F 指令執行后保留R0的低四位,其余位清0.
EOR指令
邏輯 "異或" 指令
指令格式:EOR{cond}{S}Rd,Rn,operand2
指令舉例:EOR R0,R0,R0 執行后R0 為 0
ORN指令
邏輯“或非”指令 先將操作數取反,再與目標寄存器進行或操作
指令格式:ORN指令{cond}{S}Rd,Rn,operand2 指令舉例:EOR R0,R0,#0x0F
BIC指令
位清除指令
指令格式:BIC{cond}{S}Rd,Rn,operand2
功能是將operand2的值取反,然后將結果與Rn寄存器的值相 "與" 并保存到Rd寄存器中
指令舉例:BIC R0,R0,#0X0F 將R0第四位清0,其余位保持不變
比較指令
CMP指令
指令格式: CMP{cond}Rn,operand2
CMP指令使用Rn寄存器減去operand2的值,這與SUBS指令功能相同,但CMP指令不保存計算結果,僅僅根據比較重置標志位.
4月8日更新:它影響的標志位包括CF,SF,ZF,OF,AF,PF
CF : 進位標志
PF : 奇偶標志
AF : 輔助進位標識
ZF : 0標識
SF : 符號標識
OF : 溢出標識
指令舉例:CMP R0,#0 判斷R0寄存器的值是否為0
CMN指令
指令格式: CMN{cond}Rn,operand2
CMN指令將operand2的值加到Rn寄存器上,這與ADDS的指令功能相同,不過CMN指令不保存計算結果
CMN指令舉例如下:
CMN RO,R1
TST指令
指令格式: TST{cond}Rn,operand2
TST為測試指令,它的功能是將Rn寄存器中的內容與operand2的值進行 “與” 運算,這與ANDS指令功能相同,但TST指令不保存計算結果,僅僅根據計算結果設置標志位。
指令舉例:
TEQ R0,#1 判斷R0寄存器最低位是否為1
TEQ指令
指令格式: TEQ {cond}Rn,operand2
TEQ的功能是將Rn寄存器的值和operand2的值進行 “異或” 運算,但是TEQ指令不保存計算結果,僅根據計算結果設置標志位.
指令舉例: 判斷R0寄存器與R1寄存器的值是否相等
移位指令
LSL
邏輯左移,將整個操作數向左移動兩位,右邊補0,最終操作也就是 * 2^n(移位)
指令舉例: LSL R1,R0,#2 將R0向左移動兩位,結果保存到R1中. 也就是 R0 * 2^2
LSR
邏輯右移,基本和左移操作差不多,就是整體向右移,左邊補0,最終操作也就是 / 2 ^ n(移位)
指令舉例: LSR R1,R0,#2 將R0向右移動兩位,結果保存到R1中. 也就是 R0 / 2^2