arm 指令集
ADuC702x可以用兩套指令集:ARM指令集和Thumb指令集。本小節介紹ARM指令集。在介紹ARM指令集之前,先介紹指令的格式。
A.2.1 指令格式
(1)基本格式
<opcode>{<cond>}{S} <Rd>,<Rn>{,<opcode2>}
其中,<>內的項是必須的,{}內的項是可選的,如<opcode>是指令助記符,是必須的,而{<cond>}為指令執行條件,是可選的,如果不寫則使用預設條件AL(無條件執行)。
opcode 指令助記符,如LDR,STR 等
cond 執行條件,如EQ,NE 等
S 是否影響CPSR 暫存器的值,書寫時影響CPSR,否則不影響
Rd 目標暫存器
Rn 第一個運算元的暫存器
operand2 第二個運算元
指令格式舉例如下:
LDR R0,[R1] ;讀取R1 地址上的儲存器單元內容,執行條件AL
BEQ DATAEVEN ;跳轉指令,執行條件EQ,即相等跳轉到DATAEVEN
ADDS R1,R1,#1 ;加法指令,R1+1=R1 影響CPSR 暫存器,帶有S
SUBNES R1,R1,#0xD;條件執行減法運算(NE),R1-0xD=>R1,影響CPSR 暫存器,帶有S
(2)第2個運算元
在ARM 指令中,靈活的使用第2個運算元能提高程式碼效率,第2個運算元的形式如下:
#immed_8r
常數表示式,該常數必須對應8 位點陣圖,即常數是由一個8 位的常數迴圈移位偶數位得到。
合法常量
0x3FC、0、0xF0000000、200、0xF0000001等都是合法常量。
非法常量
0x1FE、511、0xFFFF、0x1010、0xF0000010等都是非法常量。
常數表示式應用舉例如下:
MOV R0,#1 ;R0=1
AND R1,R2,#0x0F ;R2 與0x0F,結果儲存在R1
LDR R0,[R1],#-4 ;讀取R1 地址上的儲存器單元內容,且R1=R1-4
Rm
暫存器方式,在暫存器方式下運算元即為暫存器的數值。
暫存器方式應用舉例:
SUB R1,R1,R2 ;R1-R2=>R1
MOV PC,R0 ;PC=R0,程式跳轉到指定地址
LDR R0,[R1],-R2 ;讀取R1 地址上的儲存器單元內容並存入R0,且R1=R1-R2
Rm, shift
暫存器移位方式。將暫存器的移位結果作為運算元,但RM 值儲存不變,移位方法如下:
ASR #n 算術右移n 位(1≤n≤32)
LSL #n 邏輯左移n 位(1≤n≤31)
LSR #n 邏輯左移n 位(1≤n≤32)
ROR #n 迴圈右移n 位(1≤n≤31)
RRX 帶擴充套件的迴圈右移1位
type Rs 其中,type 為ASR,LSL,和ROR 中的一種;Rs 偏移量暫存器,低8位有效,若其值大於或等於32,則第2 個運算元的結果為0(ASR、ROR例外)。
暫存器偏移方式應用舉例:
ADD R1,R1,R1,LSL #3 ;R1=R1*9
SUB R1,R1,R2,LSR#2 ;R1=R1-R2*4
R15 為處理器的程式計數器PC,一般不要對其進行操作,而且有些指令是不允許使用R15,如UMULL 指令。
(3)條件碼
使用指令條件碼,可實現高效的邏輯操作,提高程式碼效率。表A-1給出條件碼錶。
表A-1 條件碼錶
對於Thumb指令集,只有B 指令具有條件碼執行功能,此指令條件碼同表A-?,但如果為無條件執行時,條件碼助記符“AL”不能在指令中書寫。
條件碼應用舉例如下:
比較兩個值大小,並進行相應加1 處理,C 程式碼為:
if(a>b)a++ ;
else b++ ;
對應的ARM 指令如下。其中R0為a,R1為b。
CMP R0,R1 ; R0 與R1 比較
ADDHI R0,R0,#1 ; 若R0>R1,則R0=R0+1
ADDLS R1,R1,#1 ;若R0<=R1,則R1=R1+1
若兩個條件均成立,則將這兩個數值相加,C程式碼為:
If((a!=10)&&(b!=20)) a=a+b;
對應的ARM 指令如下,其中R0 為a,R1 為b。
CMP R0,#10 ; 比較R0 是否為10
CMPNE R1,#20 ; 若R0 不為10,則比較R1 是否20
ADDNE R0,R0,R1 ; 若R0 不為10 且R1 不為20,指令執行,R0=R0+R1
A.2.2 ARM 儲存器訪問指令
ARM 處理是載入/儲存體系結構的典型的RISC 處理器,對儲存器的訪問只能使用載入和儲存指令實現。ARM 的載入/儲存指令是可以實現字、半字、無符/有符位元組操作;批量載入/儲存指令可實現一條指令載入/儲存多個暫存器的內容,大大提高效率;SWP指令是一 條暫存器和儲存器內容交換的指令,可用於訊號量操作等。ARM 處理器是馮?諾依曼儲存結構,程式空間、RAM 空間及IO 對映空間統一編址,除對對RAM 操作以外,對外圍IO、程式資料的訪問均要通過載入/儲存指令進行。表A-2給出ARM 儲存訪問指令表。
表A-2 ARM 儲存訪問指令表
LDR 和STR
載入/儲存字和無符號位元組指令。使用單一資料傳送指令(STR 和LDR)來裝載和儲存單一位元組或字的資料從/到記憶體。LDR 指令用於從記憶體中讀取資料放入暫存器中;STR 指令用於將暫存器中的資料儲存到記憶體。指令格式如下:
LDR{cond}{T} Rd,<地址>;載入指定地址上的資料(字),放入Rd 中
STR{cond}{T} Rd,<地址>;儲存資料(字)到指定地址的儲存單元,要儲存的資料在Rd中
LDR{cond}B{T} Rd,<地址>;載入位元組資料,放入Rd中,即Rd最低位元組有效,高24位清零
STR{cond}B{T} Rd,<地址>;儲存位元組資料,要儲存的資料在Rd,最低位元組有效
其中,T 為可選後綴,若指令有T,那麼即使處理器是在特權模式下,儲存系統也將訪問看成是處理器是在使用者模式下。T 在使用者模式下無效,不能與前索引偏移一起使用T。
LDR/STR 指令定址是非常靈活的,由兩部分組成,一部分為一個基址暫存器,可以為任一個通用暫存器,另一部分為一個地址偏移量。地址偏移量有以下3 種格式:
(1) 立即數。立即數可以是一個無符號數值,這個資料可以加到基址暫存器,也可以從基址暫存器中減去這個數值。指令舉例如下:
LDR R1,[R0,#0x12] ;將R0+0x12 地址處的資料讀出,儲存到R1 中(R0 的值不變)
LDR R1,[R0,#-0x12];將R0-0x12 地址處的資料讀出,儲存到R1 中(R0 的值不變)
LDR R1,[R0] ;將R0 地址處的資料讀出,儲存到R1 中(零偏移)
(2)暫存器。暫存器中的數值可以加到基址暫存器,也可以從基址暫存器中減去這個數值。指令舉例值。指令舉例如下:
LDR R1,[R0,R2] ;將R0+R2 地址的資料計讀出,儲存到R1 中(R0 的值不變)
LDR R1,[R0,-R2] ;將R0-R2 地址處的資料計讀出,儲存到R1 中(R0 的值不變)
(3)暫存器及移位常數。暫存器移位後的值可以加到基址暫存器,也可以從基址暫存器中減去這個數值。指令舉例如下:
LDR R1,[R0,R2,LSL #2] ;將R0+R2*4地址處的資料讀出,儲存到R1中(R0,R2的值不變)
LDR R1,[R0,-R2,LSL #2];將R0-R2*4地址處的資料計讀出,儲存到R1中(R0,R2的值不變)
從定址方式的地址計算方法分,載入/儲存指令有以下4 種形式:
(1)零偏移。Rn 的值作為傳送資料的地址,即地址偏移量為0。指令舉例如下:
LDR Rd,[Rn]
(2)前索引偏移。在資料傳送之前,將偏移量加到Rn 中,其結果作為傳送資料的儲存地址。若使用字尾“!”,則結果寫回到Rn 中,且Rn 值不允許為R15。指令舉例如下:
LDR Rd,[Rn,#0x04]!
LDR Rd,[Rn,#-0x04]
(3)程式相對偏移。程式相對偏移是索引形式的另一個版本。彙編器由PC 暫存器計算偏移量,並將PC 暫存器作為Rn 生成前索引指令。不能使用字尾“!”。指令舉例如下:
LDR Rd,label ;label 為程式標號,label 必須是在當前指令的±4KB 範圍內
(4) 後索引偏移。Rn 的值用做傳送資料的儲存地址。在資料傳送後,將偏移量與Rn相加,結果寫回到Rn 中。Rn 不允許是R15。指令舉例如下:
LDR Rd,[Rn],#0x04
地址對準--大多數情況下,必須保證用於32 位傳送的地址是32 位對準的。
載入/儲存字和無符號位元組指令舉例如下:
LDR R2,[R5] ;載入R5 指定地址上的資料(字),放入R2 中
STR R1,[R0,#0x04] ;將R1 的資料儲存到R0+0x04 儲存單元,R0 值不變
LDRB R3,[R2],#1 ;讀取R2 地址上的一位元組資料,並儲存到R3 中,R2=R3+1
STRB R6,[R7] ;讀R6 的資料儲存到R7 指定的地址中,只儲存一位元組資料
載入/儲存半字和帶符號位元組。這類LDR/STR 指令可能載入帶符位元組載入帶符號半字、載入/儲存無符號半字。偏移量格式、定址方式與載入/儲存字和無符號位元組指令相同。指令格式如下:
LDR{cond}SB Rd,<地址> ;載入指定地址上的資料(帶符號位元組),放入Rd 中
LDR{cond}SH Rd,<地址> ;載入指定地址上的資料(帶符號位元組),放入Rd 中
LDR{cond}H Rd,<地址> ;載入半字資料,放入Rd中,即Rd最低16 位有效,高16位清零
STR{cond}H Rd,<地址> ;儲存半字資料,要儲存的資料在Rd,最低16 位有效
說明:帶符號位半字/位元組載入是指帶符號位載入擴充套件到32 位;無符號位半字載入是指零擴充套件到32 位。
地址對準--對半字傳送的地址必須為偶數。非半字對準的半字載入將使Rd 內容不可靠,非半字對準的半字儲存將使指定地址的2 位元組儲存內容不可靠。
載入/儲存半字和帶符號位元組指令舉例如下:
LDRSB R1[R0,R3] ;將R0+R3 地址上的位元組資料讀出到R1,高24 位用符號位擴充套件
LDRSH R1,[R9] ;將R9 地址上的半字資料讀出到R1,高16 位用符號位擴充套件
LDRH R6,[R2],#2 ;將R2 地址上的半字資料讀出到R6,高16 位用零擴充套件,R2=R2+1
SHRH R1,[R0,#2]!;將R1 的資料儲存到R2+2 地址中,只儲存低2 位元組資料,R0=R0+2
LDR/STR 指令用於對記憶體變數的訪問,記憶體緩衝區資料的訪問、查表、外設的控制操作等等,若使用LDR 指令載入資料到PC 暫存器,則實現程式跳轉功能,這樣也就實現了程式散轉。
變數的訪問
NumCount EQU 0x40003000 ;定義變數NumCount
…
LDR R0,=NumCount ;使用LDR 偽指令裝載NumCount 的地址到R0
LDR R1,[R0] ;取出變數值
ADD R1,R1,#1 ;NumCount=NumCount+1
STR R1,[R0] ;儲存變數值
…
GPIO 設定
GPIO-BASE EQU 0Xe0028000 ;定義GPIO 暫存器的基地址
…
LDR R0,=GPIO-BASE
LDR R1,=0x00FFFF00 ;裝載32 位立即數,即設定值
STR R1,[R0,#0x0C] ;IODIR=0x00FFFF00, IODIR 的地址為0xE002800C
MOV R1,#0x00F00000
STR R1,[R0,#0x04] ;IOSET=0x00F00000,IOSET 的地址為0xE0028004
…
程式散轉
…
MOV R2,R2,LSL #2 ;功能號乘上4,以便查表
LDR PC,[PC,R2] ;查表取得對應功能子程式地址,並跳轉
NOP
FUN-TAB DCD FUN-SUB0
DCD FUN-SUB1
DCD FUN-SUB2
…
LDM 和STM
批量載入/儲存指令可以實現在一組暫存器和一塊連續的記憶體的單元之間傳輸資料。LDM 為載入多個暫存器,STM 為儲存多個暫存器。允許一條指令傳送16 個暫存器的任何子集或所有暫存器。指令格式如下:
LDM{cond}<模式> Rn{!},reglist{^}
STM{cond}<模式> Rn{!},reglist{^}
LDM /STM 的主要用途是現場保護、資料複製、引數傳送等。其模式有8 種,如下所列:(前面4 種用於資料塊的傳輸,後面4 種是堆疊操作)。
(1) IA:每次傳送後地址加4
(2) IB:每次傳送前地址加4
(3) DA:每次傳送後地址減4
(4) DB:每次傳送前地址減4
(5) FD:滿遞減堆疊
(6) ED:空遞增堆疊
(7) FA:滿遞增堆疊
(8) EA:空遞增堆疊
其中,暫存器Rn 為基址暫存器,裝有傳送資料的初始地址,Rn 不允許為R15;字尾“!”表示最後的地址寫回到Rn 中;暫存器列表reglist 可包含多於一個暫存器或暫存器範圍,使用“,”分開,如{R1,R2,R6-R9},暫存器排列由小到大排列;“^”字尾不允許在使用者模式呈系統模式下使 用,若在LDM 指令用暫存器列表中包含有PC 時使用,那麼除了正常的多暫存器傳送外,將SPSR 拷貝到CPSR 中,這可用於異常處理返回;使用“^”字尾進行資料傳送且暫存器列表不包含PC 時,載入/儲存的是使用者模式的暫存器,而不是當前模式的暫存器。
地址對準――這些指令忽略地址的位[1:0]。
批量載入/儲存指令舉例如下:
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}^;恢復現場,異常處理返回
在進行資料複製時,先設定好源資料指標,然後使用塊拷貝定址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB /STMDB 進行讀取和儲存。而進行堆疊操作時,則要先設定堆疊指標,一般使用SP 然後使用堆疊定址指令STMFD/LDMFD、STMED。LDMED、STMFA/LDMFA、STMEA/LDMEA 實現堆疊操作。
多暫存器傳送指令示意圖如圖A-1所示,其中R1為指令執行前的基址暫存器,R1’則為指令執行完後的基址暫存器。
(a)指令STMIA R1!,{R5-R7} (b)指令STMIB R1!,{R5-R7}
(c)指令STMDA R1!, {R5-R7} (d)指令STMDB R1!,{R5-R7}
圖A-1 多暫存器傳送指令示意圖
資料是儲存在基址暫存器的地址之上還是之下,地址是在儲存第一個值之前還是之後增加還是減少。表A-3給出多暫存器傳送指令對映示意表。
表A-3 多暫存器傳送指令對映示意表
使用LDM/STM 進行資料複製例程如下:
…
LDR R0,=SrcData ;設定源資料地址
LDR R1,=DstData ;設定目標地址
LDMIA R0,{R2-R9} ;載入8 字資料到暫存器R2~R9
STMIA R1,{R2-R9} ;儲存暫存器R2~R9 到目標地址
使用LDM/STM 進行現場暫存器保護,常在子程式中或異常處理使用:
SENDBYTE
STMFD SP!,{R0-R7,LR} ;暫存器入堆
…
BL DELAY ;呼叫DELAY 子程式
…
LDMFD SP!,{R0-R7,PC} ;恢復暫存器,並返回
SWP
暫存器和儲存器交換指令。SWP指令用於將一個記憶體的單元(該單元地址放在暫存器Rn中)的內容讀取到一個暫存器Rd 中,同時將另一個暫存器Rm 的內容寫入到該記憶體的單元中。使用SWP 可實現訊號量操作。
指令格式如下:
SWP{cond}{B} Rd,Rm,[Rn]
其中,B 為可選後綴,若有B,則交換位元組,否則交換32 位字:Rd 為資料從儲存器載入到的暫存器;Rm 的資料用於儲存到儲存器中,若Rm 與Rn 相同,則為暫存器與儲存器內容進行交換;Rn 為要進行資料交換的儲存器地址,Rn 不能與Rd 和Rm 相同。
SWP 指令舉例如下:
SWP R1,R1,[R0] ; 將R1 的內容與R0 指向的儲存單元的內容進行交換
SWP R1,R2,,[R0] ; 將R0 指向的儲存單元內容讀取一位元組資料到R1 中(高24 位清零)
; 並將R2 的內容寫入到該記憶體的單元中(最低位元組有效)
使用SWP 指令可以方便地進行訊號量的操作:
12C_SEM EQU 0x40003000
…
12C_SEM_WAIT
MOV R0,#0
LDR R0,=12C_SEM
SWP R1,R1,[R0] ;取出訊號量,並設定其為0
CMP R1,#0 ;判斷是否有訊號
BEQ 12C_SEM_WAIT ;若沒有訊號,則等待
A.2.3 ARM 資料處理指令
資料處理指令大致可分為3 類;資料傳送指令(如MOV、MVN),算術邏輯運算指令(如ADD,SUM,AND),比較指令(如CMP、TST)。資料處理指令只能對暫存器的內容進行操作。
所有ARM 資料處理指令均可選擇使用S 字尾,以影響狀態標誌。比較指令CMP、CMN、TST和TEQ不需要字尾S,它們會直接影響狀態標誌。ARM 資料處理指令列於表A-4中。
表A-4 ARM 資料處理指令
(1)資料傳送指令
MOV
資料傳送指令。將8 點陣圖立即數或暫存器(operant2)傳送到目標暫存器Rd,可用於移位運算等操作。指令格式如下:
MOV{cond}{S} Rd,operand2
MOV 指令舉例如下:
MOV R1#0x10 ;R1=0x10
MOV R0,R1 ;R0=R1
MOVS R3,R1,LSL #2 ;R3=R1<<2,並影響標誌位
MOV PC,LR ;PC=LR ,子程式返回
MVN
資料非傳送指令。將8 點陣圖立即數或暫存器(operand2)按位取反後傳送到目標暫存器(Rd),因為其具有取反功能,所以可以裝載範圍更廣的立即數。指令格式如下:
MVN{cond}{S} Rd,operand2
MVN 指令舉例如下:
MVN R1,#0xFF ;R1=0xFFFFFF00
MVN R1,R2 ;將R2 取反,結果存到R1
(2)算術邏輯運算指令
ADD
加法運算指令。將operand2 資料與Rn 的值相加,結果儲存到Rd 暫存器。指令格式如下:
ADD{cond}{S} Rd,Rn,operand2
ADD 指令舉例如下:
ADDS R1,R1,#1 ;R1=R1+1
ADD R1,R1,R2 ;R1=R1+R2
ADDS R3,R1,R2,LSL #2 ;R3=R1+R2<<2
SUB
減法運算指令。用暫存器Rn 減去operand2。結果儲存到Rd 中。指令格式如下:
SUB{cond}{S} Rd,Rn,operand2
SUB 指令舉例如下:
SUBS R0,R0,#1 ;R0=R0-1
SUBS R2,R1,R2 ;R2=R1-R2
SUB R6,R7,#0x10 ;R6=R7-0x10
RSB
逆向減法指令。用暫存器operand2 減法Rn,結果儲存到Rd 中。指令格式如下:
RSB{cond}{S} Rd,Rn,operand2
SUB 指令舉例如下:
RSB R3,R1,#0xFF00 ;R3=0xFF00-R1
RSBS R1,R2,R2,LSL #2 ;R1=R2<<2-R2=R2×3
RSB R0,R1,#0 ;R0=-R1
ADC
帶進位加法指令。將operand2 的資料與Rn 的值相加,再加上CPSR 中的C 條件標誌位。結果儲存到Rd 暫存器。指令格式如下:
ADC{cond}{S} Rd,Rn,operand2
ADC 指令舉例如下:
ADDS R0,R0,R2
ADC R1,R1,R3 ;使用ADC 實現64 位加法,(R1、R0)=(R1、R0)+(R3、R2)
SBC
帶進位減法指令。用暫存器Rn 減去operand2,再減去CPSR 中的C 條件標誌位的非(即若C 標誌清零,則結果減去1),結果儲存到Rd 中。指令格式如下:
SCB{cond}{S}Rd,Rn,operand2
SBC 指令舉例如下:
SUBS R0,R0,R2
SBC R1,R1,R3 ;使用SBC 實現64 位減法,(R1,R0)-(R3,R2)
RSC
帶進位逆向減法指令。用暫存器operand2 減去Rn,再減去CPSR 中的C 條件標誌位,結果儲存到Rd 中。指令格式如下:
RSC{cond}{S} Rd,Rn,operand2
RSC 指令舉例如下:
RSBS R2,R0,#0
RSC R3,R1,#0 ;使用RSC 指令實現求64 位數值的負數
AND
邏輯與操作指令。將operand2 值與暫存器Rn 的值按位作邏輯與操作,結果儲存到Rd 中。指令格式如下:
AND{cond}{S} Rd,Rn,operand2
AND 指令舉例如下:
ANDS R0,R0,#x01 ;R0=R0&0x01,取出最低位資料
AND R2,R1,R3 ;R2=R1&R3
ORR
邏輯或操作指令。將operand2 的值與暫存器Rn 的值按位作邏輯或操作,結果儲存到Rd 中。指令格式如下:
ORR{cond}{S} Rd,Rn,operand2
ORR 指令舉例如下:
ORR R0,R0,#x0F ;將R0 的低4 位置1
MOV R1,R2,LSR #4
ORR R3,R1,R3,LSL #8 ;使用ORR 指令將近R2 的高8 位資料移入到R3 低8 位中
EOR
邏輯異或操作指令。將operand2 的值與暫存器Rn 的值按位作邏輯異或操作,結果儲存到Rd 中。指令格式如下:
EOR{cond}{S}Rd,Rn,operand2
EOR 指令舉例如下:
EOR R1,R1,#0x0F ;將R1 的低4 位取反
EOR R2,R1,R0 ;R2=R1^R0
EORS R0,R5,#0x01 ;將R5 和0x01 進行邏輯異或,結果儲存到R0,並影響標誌位
BIC
位清除指令。將暫存器Rn 的值與operand2 的值的反碼按位作邏輯與操作,結果儲存到Rd 中。指令格式如下:
BIC{cond}{S}Rd,Rn,operand2
BIC 指令舉例如下:
BIC R1,R1,#0x0F ;將R1 的低4 位清零,其它位不變
BIC R1,R2,R3 ;將拭的反碼和R2 相邏輯與,結果儲存到R1
(3)比較指令
CMP
比較指令。指令使用暫存器Rn 的值減去operand2 的值,根據操作的結果更新CPSR中的相應條件標誌位,以便後面的指令根據相應的條件標誌來判斷是否執行。指令格式如下:
CMP{cond} Rn,operand2
CMP 指令舉例如下:
CMP R1,#10 ;R1 與10 比較,設定相關標誌位
CMP R1,R2 ;R1 與R2 比較,設定相關標誌位
CMP 指令與SUBS 指令的區別在於CMP 指令不儲存運算結果。在進行兩個資料大小判斷時,常用CMP 指令及相應的條件碼來操作。
CMN
負數比較指令。指令使用暫存器Rn 與值加上operand2 的值,根據操作的結果更新CPSR 中的相應條件標誌位,以便後面的指令根據相應的條件標誌來判斷是否執行,指令格式如下:
CMN{cond} Rn,operand2
CMN R0,#1 ;R0+1,判斷R0 是否為1 的補碼,若是Z 置位
CMN 指令與ADDS 指令的區別在於CMN 指令不儲存運算結果。CMN 指令可用於負數比較,比如CMNR0,#1 指令則表示R0 與-1 比較,若R0 為-(即1 的補碼),則Z 置位,否則Z復位。
TST
位測試指令。指令將暫存器Rn 的值與operand2 的值按位作邏輯與操作,根據操作的結果更新CPSR 中相應的條件標誌位,以便後面指令根據相應的條件標誌來判斷是否執行。指令格式如下:
TST{cond} Rn,operand2
TST 指令舉例如下:
TST R0,#0x01 ;判斷R0 的最低位是否為0
TST R1,#0x0F ;判斷R1 的低4 位是否為0
TST 指令與ANDS 指令的區別在於TST4 指令不儲存運算結果。TST 指令通常於EQ、NE條件碼配合使用,當所有測試位均為0 時,EQ 有效,而只要有一個測試為不為0,則NE 有效。
TEQ
相等測試指令。指令暫存器Rn 的值與operand2 的值按位作邏輯異或操作,根據操作的結果更新CPSR 中相應條件標誌位,以便後面的指令根據相應的條件標誌來判斷是否執行。指令格式如下:
TEQ{cond} Rn,operand2
TEQ 指令舉例如下:
TEQ R0,R1 ;比較R0 與R1 是否相等(不影響V 位和C 位)
TST 指令與EORS 指令的區別在於TST 指令不儲存運算結果。使用TEQ 進行相等測試,常與EQNE 條件碼配合使用,當兩個資料相等時,EQ 有效,否則NE 有效。
(4)乘法指令
ARM7TDMI(-S)具有32×32 乘法指令、32×32 乘加指令、32×32 結果為64 位的乘法指令。表A-5給出全部的ARM 乘法指令。
表A-5 全部的ARM 乘法指令
MUL
32 位乘法指令。指令將Rm 和Rs 中的值相乘,結果的低32 位儲存到Rd 中。指令格式如下:
MUL{cond}{S} Rd,Rm,Rs
MUL 指令舉例如下:
MUL R1,R2,R3 ;R1=R2×R3
MULS R0,R3,R7 ;R0=R3×R7,同時設定CPSR 中的N 位和Z 位
MLA
32 位乘加指令。指令將Rm 和Rs 中的值相乘,再將乘積加上第3 個運算元,結果的低32 位儲存到Rd 中。指令格式如下:
MLA{cond}{S} Rd,Rm,Rs,Rn
MLA 指令舉例如下:
MLA R1,R2,R3,R0 ;R1=R2×R3+10
UMULL
64 位無符號乘法指令。指令將Rm 和Rs 中的值作無符號數相乘,結果的低32 位儲存到RsLo 中,而高32 位儲存到RdHi 中。指令格式如下:
UMULL{cond}{S} RdLo,RdHi,Rm,Rs
UMULL 指令舉例如下:
UMULL R0,R1,R5,R8 ;(R1、R0)=R5×R8
UMLAL
64 位無符號乘加指令。指令將Rm 和Rs 中的值作無符號數相乘,64 位乘積與RdHi、RdLo 相加,結果的低32 位儲存到RdLo 中,而高32 位儲存到RdHi 中。指令格式如下:
UMLAL{cond}{S} RdLo,RdHi,Rm,Rs
UMLAL 指令舉例如下:
UMLAL R0,R1,R5,R8 ;(R1,R0)=R5×R8+(R1,R0)
SMULL
64 位有符號乘法指令。指令將Rm 和Rs 中的值作有符號數相乘,結果的低32 位儲存到RdLo 中,而高32 位儲存到RdHi 中。指令格式如下:
SMULL{cond}{S} RdLo,RdHi,Rm,Rs
SMULL 指令舉例如下:
SMULL R2,R3,R7,R6 ;(R3,R2)=R7×R6
SMLAL
64 位有符號乘加指令。指令將Rm 和Rs 中的值作有符號數相乘,64 位乘積與RdHi、RdLo,相加,結果的低32 位儲存到RdLo 中,而高32 位儲存到RdHi 中。指令格式如下:
SMLAL{cond}{S} RdLo,RdHi,Rm,Rs
SMLAL 指令舉例如下:
SMLAL R2,R3,R7,R6 ;(R3,R2)=R7×R6+(R3,R2)
A.2.4 ARM 跳轉指令
在ARM 中有兩種方式可以實現程式的跳轉,一種是使用跳轉指令直接跳轉,另一種則是直接向PC 暫存器賦值實現跳轉。跳轉指令有跳轉指令B,帶連結的跳轉指令BL 帶狀態切換的跳轉指令BX。表A-6給出全部的ARM跳轉指令。
表A-6 ARM跳轉指令
B
跳轉指令。跳轉到指定的地址執行程式。指令格式如下:
B{cond} label
跳轉指令B 舉例如下:
B WAITA ;跳轉到WAITA 標號處
B 0x1234 ;跳轉到絕對地址0x1234 處
跳轉到指令B 限制在當前指令的±32Mb 的範圍內。
BL
帶連結的跳轉指令。指令將下一條指令的地址拷貝到R14(即LR)連結暫存器中,然後跳轉到指定地址執行程式。指令格式如下:
BL{cond} label
帶連結的跳轉指令BL 舉例如下:
BL DELAY
跳轉指令B 限制在當前指令的±32MB 的範圍內。BL 指令用於子程式呼叫。
BX
帶狀態切換的跳轉指令。跳轉到Rm 指定的地址執行程式,若Rm 的位[0]為1,則跳轉時自動將CPSR 中的標誌T 置位,即把目標地址的程式碼解釋為Thumb 程式碼;若Rm 的位[0]為0,則跳轉時自動將CPSR 中的標誌T 復位,即把目標地址的程式碼解釋為ARM 程式碼。指令格式如下:
BX{cond} Rm
帶狀態切換的跳轉指令BX 舉例如下:
ADRL R0,ThumbFun+1
BX R0 ;跳轉到R0 指定的地址,並根據R0 的最低位來切換處理器狀態