天天看點

ARM技術概論|ARM指令

ARM指令

1. ARM指令集

1.1 資料處理指令

助記符 操作 助記符 操作
MOV 資料傳送 AND 邏輯與
MVN 資料取反傳送 ORR 邏輯或
ADD EOR 邏輯異或
ADC 帶進位的加 BIC 位清零
SUB CMP 比較
SBC 帶借位的減 CMN 相反數比較
RSB 逆向減 TST 位測試
RSC 帶借位逆向減 TEQ 測試相等
/*****資料處理指令示例*****/
MOV   R0, #0xFF   //R0 = 0xFF
MOV   R0, R0      //R0 = R0...NOP指令
MOV   R0, R0, LSL#3 //R0 = R0 << 3
MOV   PC, R14     //退出到調用者,用于普通函數傳回,PC即R15
MOVS  PC, R14     //退出到調用者并恢複标志位,用于異常函數傳回
MVN   R0, #4      //R0 = ~(4)
MVN   R0, #0      //R0 = ~(0)
ADD   R0, R1, R2    //R0 = R1 + R2
ADD   R0, R1, #0xFF //R0 = R1 + 0xFF
ADD   R0, R2, R3, LSL#1 //R0 = R2 + (R3 << 1)
ADDS  R0, R4, R8      //加低端的字
ADCS  R1, R5, R9      //加下1個字,帶進位
ADCS  R2, R6, R10     //加第3個字,帶進位
ADCS  R3, R7, R11     //加高端的字,帶進位
SUB   R0, R1, R2      //R0 = R1 - R2
SUB   R0, R1, #0xFF   //R0 = R1 - 0xFF
SUB   R0, R2, R3, LSL#1 //R0 = R2 - (R3 << 1)
SUBS  R0, R0, R2      //低位相減結果存儲在R0,同時更新CPSR中對應的條件标志位
SBCS  R1, R1, R3      //高位相減同時減去低位的借位 R1 = R1 - R3 - (!C)
RSB   R2, R0, #0xFF   //R2 = 0xFF - R0
RSBS  R2, R0, #0      //
RSC   R3, R1, #0      //
AND   R0, R0, #0x03   //R0寄存器的0、1位不變,其他位清零
AND   R2, R1, R3      //R2 = R1 & R3
AND   R0, R0, #0x01   //R0 = R0 & 0x01
ORR   R0, R0, #0x03   //R0寄存器的0、1位設定為1
ORR   R0, R0, #0x0F   //R0寄存器的低4位設定為1
EOR   R0, R0, #0x03   //反轉R0中的第0和1位
EOR   R1, R1, #0x0F   //将R1的低4位取反
EOR   R2, R1, R0      //R2 = R1 ^ R0
EORS  R0, R5, #0x01   //将R5和0x01進行邏輯異或,結果儲存到R0,并根據執行結果更新标志位
BIC   R0, R0, #0x1011   //清除R0中的位0、1和3,保持其餘的不變
BIC   R1, R2, R3      //将R3的反碼和R2邏輯與,結果儲存到R1中
CMP   R1, #10       //比較R1和立即數10并更新相關的标志位
CMP   R1, R2        //比較R1和R2中的值并設定相關的标志位
CMN   R0, #1        //
TST   R0, #1        //測試R0的最低位是否為0
TEQ   R0, R1        //比較R0和R1是否相等,不影響CPSR中的V位和C位
      

1.2 乘法指令

助記符 操作 助記符 操作
MUL 乘(保留32位結果) UMLAL 無符号數長乘–累加
MLA 乘(32位結果) SMULL 有符号數長乘
UMULL 無符号數長乘 SMLAL 有符号數長乘–累加
/***** 乘法指令示例*****/
MUL   R1, R2, R3      //R0 = R2 * R3
MULS  R0, R3, R7      //R0 = R3 * R7,并根據運算結果更新CPSR中的N位和Z位
MLA   R1, R2, R3, R0    //R1 = R2*R3 + R0
UMULL R0, R1, R5, R8    //R0 = R5*R8[31:0];  R1 = R5*R8[63:32]
UMLAL R0, R1, R5, R8    //R0 = R5*R8[31:0] + R0;  R1 = R5*R8[63:32] + R1
SMULL R2, R3, R7, R6    //R2 = (R7*R6)[31:0];  R3 = (R7*R6)[63:32]
SMLAL R2, R3, R7, R6    //R2 = (R7*R6)[31:0] + R2;  R3 = (R7*R6)[63:32] + R3
      

1.3 跳轉指令

助記符 操作 助記符 操作
B 跳轉 BL 帶傳回的連接配接跳轉
BX 跳轉并切換狀态 BLX 帶傳回的跳轉并切換狀态
/***** 跳轉指令示例*****/
B   LABLE   //跳轉到LABLE标号處
B   0x1234    //跳轉到絕對位址0x1234處
BL    func    //跳轉到子程式func處執行
BX    R14     //從Thumb狀态傳回到ARM狀态
      

1.4 Load/Store指令

  • 單寄存器的Load/Store指令
助記符 操作 助記符 操作
LDR 把存儲器中的一個字裝入寄存器 LDRBT 使用者模式下将一個位元組裝入寄存器
STR 将寄存器中的字儲存到存儲器 STRBT 使用者模式下将寄存器中的低8位位元組儲存到存儲器
LDRB 把一個位元組裝入一個寄存器 LDRT 使用者模式下把一個字裝入寄存器
STRB 将寄存器中的低8位位元組儲存到存儲器 STRT 使用者模式下将存儲器中的字儲存到寄存器
LDRH 把一個半字裝入一個寄存器 LDRSB 把一個有符号位元組裝入寄存器
STRH 将寄存器中的低16位半字儲存到存儲器 LDRSH 把一個有符号半字裝入寄存器
/***** 單寄存器的Load/Store指令示例*****/
LDR   R1, [R0, #0x12]     //将R0+0x12位址處的資料讀出,儲存到R1中
LDR   R1, [R0, R2, LSL#2]   //将R0+(R2<<2)位址處的資料讀出,儲存到R1中
LDR   Rd, [Rn], #0x04     //Rn位址中的資料傳送到Rd,傳送完成後Rn=Rn+0x04
STR   R1, [R0]        //儲存變量
      
  • 多寄存器的Load/Store指令
助記符 操作 助記符 操作
LDM 裝載多個寄存器 STM 儲存多個寄存器
/*****多寄存器的Load/Store指令示例*****/
LDMIA   R0!, {R3~R9}      //加載R0指向的位址上的多字資料,儲存到R3~R9中,R0值更新
STMIA   R1!, {R3~R9}      //将R3~R9的資料存儲到R1指向的位址上,R1值更新
STMFD   SP!, {R0~R7, LR}    //現場儲存,将R0~R7,LR入棧
LDMFD   SP!, {R0~R7, PC} ^    //恢複現場,異常處理傳回,同時恢複SPSR中的值到CPSR
      
  • 單資料交換指令
助記符 操作 助記符 操作
SWP 字交換 SWPB 位元組交換
/*****單資料交換指令示例*****/
SWP   R1, R1, [R0]    //将R1的内容與R0指向的存儲單元内容進行交換
SWPB  R1, R2, [R0]    //将R0指向的存儲單元内容讀取一位元組資料到R1中,在将R2寄存器中的資料存儲到R0指向的記憶體單元中
      

1.5 狀态寄存器傳輸指令

助記符 操作 助記符 操作
MRS 把程式狀态寄存器(PSR)的值送到通用寄存器 MSR 把通用寄存器的值送到PSR或把一個立即數送到PSR
/*****狀态寄存器傳輸指令示例*****/
MRS   R1, CPSR    //将CPSR狀态寄存器讀出,儲存到R1中
MRS   R2, SPSR    //将SPSR狀态寄存器讀出,儲存到R2中
MSR   CPSR_c, 0xD3  //CPSR[7:0] = 0xD3, 切換到管理模式
MSR   CPSR_cxsf, R3 //CPSR = R3
      

1.6 協處理指令

助記符 操作 助記符 操作
CDP 協處理器資料操作 MRC 從協處理器寄存器傳資料到ARM寄存器
LDC 裝載協處理器寄存器 STC 存儲協處理器寄存器
MCR 從ARM寄存器傳資料到協處理器寄存器

1.7 異常産生指令

助記符 操作 助記符 操作
SWI 軟中斷指令 BKPT 斷點中斷指令
/*****異常産生指令示例*****/
SWI   0     //産生軟中斷,中斷立即數為0
SWI   0x123456  //産生軟中斷,中斷立即數為0x123456
      

2. ARM指令的尋址方式

2.1 資料處理指令操作數的尋址方式

ARM資料處理指令的基本文法格式如下示:

<opcode> {<cond>} {S} <Rd>, <Rn>, <shifter_operand>
  • 立即數尋址:指令中的第二操作數<shifter_operand>是立即數
/*****立即數尋址示例*****/
//下面是一些應用立即數的指令
MOV   R0, #0       //送0到R0
ADD   R3, R3, #1     //R3的值加1
CMP   R7, #1000    //R7的值和1000比較
BIC   R9, R8, #0xff00  //将R8中8~15位清零,結果儲存在R9中
      
  • 寄存器尋址:指令中的第二操作數<shifter_operand>是寄存器中的值
/*****寄存器尋址示例*****/
MOV   R2, R0      //R0的值送R2
ADD   R4, R3, R2    //R2加R3,結果送R4
CMP   R7, R8      //比較R7和R8的值
      
  • 寄存器移位尋址:指令中的第二操作數<shifter_operand>是由寄存器中的值移位得到
/*****寄存器移位尋址示例*****/
//下面是使用移位操作的例子
ADD   R2, R0, R1, LSR#5
MOV   R1, R0, LSL#1
RSB   R9, R5, R5, LSL#1
      

2.2 字及無符号位元組的Load/Store指令的尋址方式

  • 寄存器間接尋址:将位址放在一個通用寄存器中,即所需要的操作數儲存在寄存器指定位址的存儲單元中,即寄存器中的值為操作數的位址指針。寄存器間接尋址字及無符号位元組的Load/Store指令文法格式如下示:
LDR|STR {<cond>} {B} {T} <Rd>, [Rm]
/*****寄存器間接尋址示例*****/
LDR   R1, [R2]  //将R2中的數值作為位址,取出此位址中的資料儲存在R1中
STR   R1, [R2]  //将R2中的數值作為位址,取出R1中的值存入R2所指向的位址
      
  • 基址變址尋址:是将基位址寄存器的内容與指令中給出的偏移量相加,形成操作數的有效位址。基址變址尋址的Load/Store指令文法格式如下示
LDR|STR {<cond>} {B} {T} <Rd>, [Rm, ±<addressing_mode>]
/*****基址變址尋址示例*****/
LDR   R1, [R0, #0x0f]   //将R0中的數值加0x0f作為位址,取出此位址的數值儲存在R1中
STR   R1, [R0, #-2]   //将R0中的數值減2作為位址,把R1中的内容儲存到此位址位置
STR   R1, [R0, +R2]   //将R0的值加上R2的值作為位址,把R1的内容儲存在該位址中
      

2.3 批量Load/Store指令的尋址方式

  • 多寄存器/塊拷貝尋址:将一片連續記憶體單元的資料加載到通用寄存器組中或将一組通用寄存器的資料存儲到連續的記憶體單元中。該類的指令文法格式如下示:
LDM|STM {<cond>} <addressing_mode> <Rn> { ! }, < registers/>< ^/>
/*****多寄存器/塊拷貝尋址示例*****/
STMIA R0!, {R1-R7}  //将R1~R7的資料儲存到R0所指向的存儲器中,R0的值之後增加,增長方向為向上增長,類似于C語言中的i++
STMIB RO!, {R1-R7}  //R0的值先增加,後将R1~R7的資料儲存到R0所指向的存儲器中,增長方向為向上增長,類似于C語言中的++i
STMDA R0!, {R1-R7}  //将R1~R7的資料儲存到R0所指向的存儲器中,R0的值之後減少,增長方向為向下增長,類似于C語言中的i--
STMDB RO!, {R1-R7}  //R0的值先減少,後将R1~R7的資料儲存到R0所指向的存儲器中,增長方向為向下增長,類似于C語言中的--i
      
  • 堆棧操作尋址方式:對于堆棧的操作,資料寫入記憶體和從記憶體中讀出要使用不同的尋址模式,因為進棧操作和出棧操作要在不同的方向上調整堆棧操作

根據不同的尋址方式,堆棧可分為:Full棧、Empty棧、遞減棧、遞增棧

根據堆棧的不同種類,尋址方式可分為:滿遞減FD、空遞減ED、滿遞增FA、空遞增EA

2.4 相對尋址

相對尋址是基址尋址的一種變通,由程式計數器PC提供基準位址,指令中的位址碼字段作為偏移量,兩者相加後得到的位址即為操作數的有效位址。有 B 和 BL 指令

/*****相對尋址示例*****/
BL  FUN1  //調用到FUN1子程式
B LOOP  //條件跳轉到LOOP标号處
      
關注我的公衆号,共同交流學習嵌入式開發相關技術:

繼續閱讀