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、5十一、0xFFFF、0x10十、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 存儲訪問指令表。code

表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~R七、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 位加法,(R一、R0)=(R一、R0)+(R三、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 ;(R一、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 的最低位來切換處理器狀態

相關文章
相關標籤/搜索