ARM 指令集
http://wenku.baidu.com/view/7efbd1116edb6f1aff001fc9.html?文章轉(zhuǎn)載于該網(wǎng)頁,留下記號(hào),以后供參考~謝謝作者!
ARM指令集詳解
ARM可以用兩套指令集:ARM指令集和Thumb指令集。本文介紹ARM指令集。在介紹ARM指令集之前,先介紹指令的格式。
1? 指令格式
??????? (1)基本格式
??????? <opcode>{<cond>}{S}<Rd>,<Rn>{,<opcode2>}
??????? 其中,<>內(nèi)的項(xiàng)是必須的,{}內(nèi)的項(xiàng)是可選的,如<opcode>是指令助記符,是必須的,而{<cond>}為指令執(zhí)行條件,是可選的,如果不寫則使用默認(rèn)條件AL(無條件執(zhí)行)。
??????? opcode? 指令助記符,如LDR,STR 等
??????? cond? 執(zhí)行條件,如EQ,NE 等
??????? S? 是否影響CPSR寄存器的值,書寫時(shí)影響CPSR,否則不影響
??????? Rd? 目標(biāo)寄存器
??????? Rn? 第一個(gè)操作數(shù)的寄存器
??????? operand2? 第二個(gè)操作數(shù)
??????? 指令格式舉例如下:
??????? LDR R0,[R1] ;讀取R1 地址上的存儲(chǔ)器單元內(nèi)容,執(zhí)行條件AL
??????? BEQ DATAEVEN ;跳轉(zhuǎn)指令,執(zhí)行條件EQ,即相等跳轉(zhuǎn)到DATAEVEN
??????? ADDS R1,R1,#1 ;加法指令,R1+1=R1 影響CPSR 寄存器,帶有S
??????? SUBNES R1,R1,#0xD;條件執(zhí)行減法運(yùn)算(NE),R1-0xD=>R1,影響CPSR 寄存器,帶有S
??????? (2)第2個(gè)操作數(shù)
??????? 在ARM 指令中,靈活的使用第2個(gè)操作數(shù)能提高代碼效率,第2個(gè)操作數(shù)的形式如下:
??????? #immed_8r
??????? 常數(shù)表達(dá)式,該常數(shù)必須對(duì)應(yīng)8 位位圖,即常數(shù)是由一個(gè)8 位的常數(shù)循環(huán)移位偶數(shù)位得到。
??????? 合法常量
??????? 0x3FC、0、0xF0000000、200、0xF0000001等都是合法常量。
??????? 非法常量
??????? 0x1FE、511、0xFFFF、0x1010、0xF0000010等都是非法常量。
??????? 常數(shù)表達(dá)式應(yīng)用舉例如下:
??????? MOV R0,#1 ;R0=1
??????? AND R1,R2,#0x0F ;R2 與0x0F,結(jié)果保存在R1
??????? LDR R0,[R1],#-4;讀取R1 地址上的存儲(chǔ)器單元內(nèi)容,且R1=R1-4
??????? Rm
??????? 寄存器方式,在寄存器方式下操作數(shù)即為寄存器的數(shù)值。
??????? 寄存器方式應(yīng)用舉例:
??????? SUB R1,R1,R2 ;R1-R2=>R1
??????? MOV PC,R0 ;PC=R0,程序跳轉(zhuǎn)到指定地址
??????? LDR R0,[R1],-R2 ;讀取R1 地址上的存儲(chǔ)器單元內(nèi)容并存入R0,且R1=R1-R2
??????? Rm, shift
??????? 寄存器移位方式。將寄存器的移位結(jié)果作為操作數(shù),但RM 值保存不變,移位方法如下:
??????? ASR #n? 算術(shù)右移n 位(1≤n≤32)
??????? LSL #n? 邏輯左移n 位(1≤n≤31)
??????? LSR #n? 邏輯左移n 位(1≤n≤32)
??????? ROR #n? 循環(huán)右移n 位(1≤n≤31)
??????? RRX? 帶擴(kuò)展的循環(huán)右移1位
??????? type Rs? 其中,type 為ASR,LSL,和ROR 中的一種;Rs 偏移量寄存器,低8位有效,若其值大于或等于32,則第2 個(gè)操作數(shù)的結(jié)果為0(ASR、ROR例外)。
??????? 寄存器偏移方式應(yīng)用舉例:
??????? ADD R1,R1,R1,LSL #3 ;R1=R1*9
??????? SUB R1,R1,R2,LSR#2 ;R1=R1-R2*4
??????? R15 為處理器的程序計(jì)數(shù)器PC,一般不要對(duì)其進(jìn)行操作,而且有些指令是不允許使用R15,如UMULL 指令。
??????? (3)條件碼
??????? 使用指令條件碼,可實(shí)現(xiàn)高效的邏輯操作,提高代碼效率。表A-1給出條件碼表。
表A-1? 條件碼表
??????? 對(duì)于Thumb指令集,只有B 指令具有條件碼執(zhí)行功能,此指令條件碼同表A-?,但如果為無條件執(zhí)行時(shí),條件碼助記符“AL”不能在指令中書寫。
??????? 條件碼應(yīng)用舉例如下:
??????? 比較兩個(gè)值大小,并進(jìn)行相應(yīng)加1 處理,C 代碼為:
??????? if(a>b)a++??? ??? ;
??????? else b++?????? ??? ;
??????? 對(duì)應(yīng)的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
??????? 若兩個(gè)條件均成立,則將這兩個(gè)數(shù)值相加,C代碼為:
??????? If((a!=10)&&(b!=20)) a=a+b;
??????? 對(duì)應(yīng)的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,指令執(zhí)行,R0=R0+R1
2? ARM 存儲(chǔ)器訪問指令
??????? ARM 處理是加載/存儲(chǔ)體系結(jié)構(gòu)的典型的RISC 處理器,對(duì)存儲(chǔ)器的訪問只能使用加載和存儲(chǔ)指令實(shí)現(xiàn)。ARM 的加載/存儲(chǔ)指令是可以實(shí)現(xiàn)字、半字、無符/有符字節(jié)操作;批量加載/存儲(chǔ)指令可實(shí)現(xiàn)一條指令加載/存儲(chǔ)多個(gè)寄存器的內(nèi)容,大大提高效率;SWP指令是一 條寄存器和存儲(chǔ)器內(nèi)容交換的指令,可用于信號(hào)量操作等。ARM 處理器是馮?諾依曼存儲(chǔ)結(jié)構(gòu),程序空間、RAM 空間及IO 映射空間統(tǒng)一編址,除對(duì)對(duì)RAM 操作以外,對(duì)外圍IO、程序數(shù)據(jù)的訪問均要通過加載/存儲(chǔ)指令進(jìn)行。表A-2給出ARM 存儲(chǔ)訪問指令表。
表A-2? ARM 存儲(chǔ)訪問指令表
????? ?? ??? LDR 和STR
??????? 加載/存儲(chǔ)字和無符號(hào)字節(jié)指令。使用單一數(shù)據(jù)傳送指令(STR 和LDR)來裝載和存儲(chǔ)單一字節(jié)或字的數(shù)據(jù)從/到內(nèi)存。LDR 指令用于從內(nèi)存中讀取數(shù)據(jù)放入寄存器中;STR 指令用于將寄存器中的數(shù)據(jù)保存到內(nèi)存。指令格式如下:
??????? LDR{cond}{T} Rd,<地址>;加載指定地址上的數(shù)據(jù)(字),放入Rd 中
??????? STR{cond}{T} Rd,<地址>;存儲(chǔ)數(shù)據(jù)(字)到指定地址的存儲(chǔ)單元,要存儲(chǔ)的數(shù)據(jù)在Rd中
??????? LDR{cond}B{T} Rd,<地址>;加載字節(jié)數(shù)據(jù),放入Rd中,即Rd最低字節(jié)有效,高24位清零
??????? STR{cond}B{T} Rd,<地址>;存儲(chǔ)字節(jié)數(shù)據(jù),要存儲(chǔ)的數(shù)據(jù)在Rd,最低字節(jié)有效
??????? 其中,T 為可選后綴,若指令有T,那么即使處理器是在特權(quán)模式下,存儲(chǔ)系統(tǒng)也將訪問看成是處理器是在用戶模式下。T 在用戶模式下無效,不能與前索引偏移一起使用T。
??????? LDR/STR 指令尋址是非常靈活的,由兩部分組成,一部分為一個(gè)基址寄存器,可以為任一個(gè)通用寄存器,另一部分為一個(gè)地址偏移量。地址偏移量有以下3 種格式:
??????? (1) 立即數(shù)。立即數(shù)可以是一個(gè)無符號(hào)數(shù)值,這個(gè)數(shù)據(jù)可以加到基址寄存器,也可以從基址寄存器中減去這個(gè)數(shù)值。指令舉例如下:
??????? LDR R1,[R0,#0x12] ;將R0+0x12 地址處的數(shù)據(jù)讀出,保存到R1 中(R0 的值不變)
??????? LDR R1,[R0,#-0x12];將R0-0x12 地址處的數(shù)據(jù)讀出,保存到R1 中(R0 的值不變)
??????? LDR R1,[R0] ;將R0 地址處的數(shù)據(jù)讀出,保存到R1 中(零偏移)
??????? (2)寄存器。寄存器中的數(shù)值可以加到基址寄存器,也可以從基址寄存器中減去這個(gè)數(shù)值。指令舉例值。指令舉例如下:
??????? LDR R1,[R0,R2] ;將R0+R2 地址的數(shù)據(jù)計(jì)讀出,保存到R1 中(R0 的值不變)
??????? LDR R1,[R0,-R2] ;將R0-R2 地址處的數(shù)據(jù)計(jì)讀出,保存到R1 中(R0 的值不變)
??????? (3)寄存器及移位常數(shù)。寄存器移位后的值可以加到基址寄存器,也可以從基址寄存器中減去這個(gè)數(shù)值。指令舉例如下:
??????? LDR R1,[R0,R2,LSL #2] ;將R0+R2*4地址處的數(shù)據(jù)讀出,保存到R1中(R0,R2的值不變)
??????? LDR R1,[R0,-R2,LSL #2];將R0-R2*4地址處的數(shù)據(jù)計(jì)讀出,保存到R1中(R0,R2的值不變)
??????? 從尋址方式的地址計(jì)算方法分,加載/存儲(chǔ)指令有以下4 種形式:
??????? (1)零偏移。Rn 的值作為傳送數(shù)據(jù)的地址,即地址偏移量為0。指令舉例如下:
??????? LDR Rd,[Rn]
??????? (2)前索引偏移。在數(shù)據(jù)傳送之前,將偏移量加到Rn 中,其結(jié)果作為傳送數(shù)據(jù)的存儲(chǔ)地址。若使用后綴“!”,則結(jié)果寫回到Rn 中,且Rn 值不允許為R15。指令舉例如下:
??????? LDR Rd,[Rn,#0x04]!
??????? LDR Rd,[Rn,#-0x04]
??????? (3)程序相對(duì)偏移。程序相對(duì)偏移是索引形式的另一個(gè)版本。匯編器由PC 寄存器計(jì)算偏移量,并將PC 寄存器作為Rn 生成前索引指令。不能使用后綴“!”。指令舉例如下:
??????? LDR Rd,label ;label 為程序標(biāo)號(hào),label 必須是在當(dāng)前指令的±4KB 范圍內(nèi)
??????? (4) 后索引偏移。Rn的值用做傳送數(shù)據(jù)的存儲(chǔ)地址。在數(shù)據(jù)傳送后,將偏移量與Rn相加,結(jié)果寫回到Rn 中。Rn 不允許是R15。指令舉例如下:
??????? LDR Rd,[Rn],#0x04
??????? 地址對(duì)準(zhǔn)--大多數(shù)情況下,必須保證用于32 位傳送的地址是32 位對(duì)準(zhǔn)的。
??????? 加載/存儲(chǔ)字和無符號(hào)字節(jié)指令舉例如下:
??????? LDR R2,[R5] ;加載R5 指定地址上的數(shù)據(jù)(字),放入R2 中
??????? STR R1,[R0,#0x04] ;將R1 的數(shù)據(jù)存儲(chǔ)到R0+0x04 存儲(chǔ)單元,R0 值不變
??????? LDRB R3,[R2],#1 ;讀取R2 地址上的一字節(jié)數(shù)據(jù),并保存到R3 中,R2=R3+1
??????? STRB R6,[R7] ;讀R6 的數(shù)據(jù)保存到R7 指定的地址中,只存儲(chǔ)一字節(jié)數(shù)據(jù)
??????? 加載/存儲(chǔ)半字和帶符號(hào)字節(jié)。這類LDR/STR 指令可能加載帶符字節(jié)\加載帶符號(hào)半字、加載/存儲(chǔ)無符號(hào)半字。偏移量格式、尋址方式與加載/存儲(chǔ)字和無符號(hào)字節(jié)指令相同。指令格式如下:
??????? LDR{cond}SB Rd,<地址> ;加載指定地址上的數(shù)據(jù)(帶符號(hào)字節(jié)),放入Rd 中
??????? LDR{cond}SH Rd,<地址> ;加載指定地址上的數(shù)據(jù)(帶符號(hào)字節(jié)),放入Rd 中
??????? LDR{cond}H Rd,<地址> ;加載半字?jǐn)?shù)據(jù),放入Rd中,即Rd最低16 位有效,高16位清零
??????? STR{cond}H Rd,<地址> ;存儲(chǔ)半字?jǐn)?shù)據(jù),要存儲(chǔ)的數(shù)據(jù)在Rd,最低16 位有效
??????? 說明:帶符號(hào)位半字/字節(jié)加載是指帶符號(hào)位加載擴(kuò)展到32 位;無符號(hào)位半字加載是指零擴(kuò)展到32位。
??????? 地址對(duì)準(zhǔn)--對(duì)半字傳送的地址必須為偶數(shù)。非半字對(duì)準(zhǔn)的半字加載將使Rd 內(nèi)容不可靠,非半字對(duì)準(zhǔn)的半字存儲(chǔ)將使指定地址的2 字節(jié)存儲(chǔ)內(nèi)容不可靠。
??????? 加載/存儲(chǔ)半字和帶符號(hào)字節(jié)指令舉例如下:
??????? LDRSB R1[R0,R3] ;將R0+R3 地址上的字節(jié)數(shù)據(jù)讀出到R1,高24 位用符號(hào)位擴(kuò)展
??????? LDRSH R1,[R9] ;將R9 地址上的半字?jǐn)?shù)據(jù)讀出到R1,高16位用符號(hào)位擴(kuò)展
??????? LDRH R6,[R2],#2 ;將R2 地址上的半字?jǐn)?shù)據(jù)讀出到R6,高16位用零擴(kuò)展,R2=R2+1
??????? SHRH R1,[R0,#2]!;將R1 的數(shù)據(jù)保存到R2+2 地址中,只存儲(chǔ)低2 字節(jié)數(shù)據(jù),R0=R0+2
??????? LDR/STR 指令用于對(duì)內(nèi)存變量的訪問,內(nèi)存緩沖區(qū)數(shù)據(jù)的訪問、查表、外設(shè)的控制操作等等,若使用LDR 指令加載數(shù)據(jù)到PC 寄存器,則實(shí)現(xiàn)程序跳轉(zhuǎn)功能,這樣也就實(shí)現(xiàn)了程序散轉(zhuǎn)。
??????? 變量的訪問
??????? NumCount EQU 0x40003000 ;定義變量NumCount
??????? …
??????? LDR R0,=NumCount ;使用LDR 偽指令裝載NumCount 的地址到R0
??????? LDR R1,[R0] ;取出變量值
??????? ADD R1,R1,#1 ;NumCount=NumCount+1
??????? STR R1,[R0] ;保存變量值
??????? …
??????? GPIO 設(shè)置
??????? GPIO-BASE EQU 0Xe0028000 ;定義GPIO 寄存器的基地址
??????? …
??????? LDR R0,=GPIO-BASE
??????? LDR R1,=0x00FFFF00 ;裝載32 位立即數(shù),即設(shè)置值
??????? STR R1,[R0,#0x0C] ;IODIR=0x00FFFF00, IODIR 的地址為0xE002800C
??????? MOV R1,#0x00F00000
??????? STR R1,[R0,#0x04] ;IOSET=0x00F00000,IOSET 的地址為0xE0028004
??????? …
??????? 程序散轉(zhuǎn)
??????? …
??????? MOV R2,R2,LSL #2 ;功能號(hào)乘上4,以便查表
??????? LDR PC,[PC,R2] ;查表取得對(duì)應(yīng)功能子程序地址,并跳轉(zhuǎn)
??????? NOP
??????? FUN-TAB DCD FUN-SUB0
??????? DCD FUN-SUB1
??????? DCD FUN-SUB2
??????? …
???????LDM 和STM
??????? 批量加載/存儲(chǔ)指令可以實(shí)現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元之間傳輸數(shù)據(jù)。LDM 為加載多個(gè)寄存器,STM 為存儲(chǔ)多個(gè)寄存器。允許一條指令傳送16 個(gè)寄存器的任何子集或所有寄存器。指令格式如下:
??????? LDM{cond}<模式> Rn{!},reglist{^}
??????? STM{cond}<模式> Rn{!},reglist{^}
??????? LDM /STM 的主要用途是現(xiàn)場(chǎng)保護(hù)、數(shù)據(jù)復(fù)制、參數(shù)傳送等。其模式有8 種,如下所列:(前面4 種用于數(shù)據(jù)塊的傳輸,后面4 種是堆棧操作)。
??????? (1) IA:每次傳送后地址加4
??????? (2) IB:每次傳送前地址加4
??????? (3) DA:每次傳送后地址減4
??????? (4) DB:每次傳送前地址減4
??????? (5) FD:滿遞減堆棧
??????? (6) ED:空遞增堆棧
??????? (7) FA:滿遞增堆棧
??????? (8) EA:空遞增堆棧
??????? 其中,寄存器Rn 為基址寄存器,裝有傳送數(shù)據(jù)的初始地址,Rn 不允許為R15;后綴“!”表示最后的地址寫回到Rn 中;寄存器列表reglist 可包含多于一個(gè)寄存器或寄存器范圍,使用“,”分開,如{R1,R2,R6-R9},寄存器排列由小到大排列;“^”后綴不允許在用戶模式呈系統(tǒng)模式下使 用,若在LDM 指令用寄存器列表中包含有PC 時(shí)使用,那么除了正常的多寄存器傳送外,將SPSR 拷貝到CPSR 中,這可用于異常處理返回;使用“^”后綴進(jìn)行數(shù)據(jù)傳送且寄存器列表不包含PC 時(shí),加載/存儲(chǔ)的是用戶模式的寄存器,而不是當(dāng)前模式的寄存器。
??????? 地址對(duì)準(zhǔn)――這些指令忽略地址的位[1:0]。
??????? 批量加載/存儲(chǔ)指令舉例如下:
??????? LDMIA R0!,{R3-R9} ;加載R0 指向的地址上的多字?jǐn)?shù)據(jù),保存到R3~R9 中,R0 值更新
??????? STMIA R1!,{R3-R9} ;將R3~R9 的數(shù)據(jù)存儲(chǔ)到R1 指向的地址上,R1 值更新
??????? STMFD SP!,{R0-R7,LR} ;現(xiàn)場(chǎng)保存,將R0~R7、LR 入棧
??????? LDMFD SP!,{R0-R7,PC}^;恢復(fù)現(xiàn)場(chǎng),異常處理返回
??????? 在進(jìn)行數(shù)據(jù)復(fù)制時(shí),先設(shè)置好源數(shù)據(jù)指針,然后使用塊拷貝尋址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB /STMDB 進(jìn)行讀取和存儲(chǔ)。而進(jìn)行堆棧操作時(shí),則要先設(shè)置堆棧指針,一般使用SP 然后使用堆棧尋址指令STMFD/LDMFD、STMED。LDMED、STMFA/LDMFA、STMEA/LDMEA 實(shí)現(xiàn)堆棧操作。
??????? 多寄存器傳送指令示意圖如圖A-1所示,其中R1為指令執(zhí)行前的基址寄存器,R1’則為指令執(zhí)行完后的基址寄存器。
(a)指令STMIA R1!,{R5-R7}????? ? ? ?? ? ? ? ? ? ? ? ???? (b)指令STMIBR1!,{R5-R7}
?
(c)指令STMDA R1!,{R5-R7}?????? ? ? ? ? ?? ? ? ? ? ? ?? ? (d)指令STMDB R1!,{R5-R7}
圖A-1? 多寄存器傳送指令示意圖
??????? 數(shù)據(jù)是存儲(chǔ)在基址寄存器的地址之上還是之下,地址是在存儲(chǔ)第一個(gè)值之前還是之后增加還是減少。表A-3給出多寄存器傳送指令映射示意表。
表A-3? 多寄存器傳送指令映射示意表
?????? 使用LDM/STM 進(jìn)行數(shù)據(jù)復(fù)制例程如下:
??????? …
??????? LDR R0,=SrcData ;設(shè)置源數(shù)據(jù)地址
??????? LDR R1,=DstData ;設(shè)置目標(biāo)地址
??????? LDMIA R0,{R2-R9} ;加載8 字?jǐn)?shù)據(jù)到寄存器R2~R9
??????? STMIA R1,{R2-R9} ;存儲(chǔ)寄存器R2~R9 到目標(biāo)地址
??????? 使用LDM/STM 進(jìn)行現(xiàn)場(chǎng)寄存器保護(hù),常在子程序中或異常處理使用:
??????? SENDBYTE
??????? STMFD SP!,{R0-R7,LR} ;寄存器入堆
??????? …
??????? BL DELAY ;調(diào)用DELAY子程序
??????? …
??????? LDMFD SP!,{R0-R7,PC} ;恢復(fù)寄存器,并返回
??????? SWP
??????? 寄存器和存儲(chǔ)器交換指令。SWP指令用于將一個(gè)內(nèi)存單元(該單元地址放在寄存器Rn中)的內(nèi)容讀取到一個(gè)寄存器Rd 中,同時(shí)將另一個(gè)寄存器Rm 的內(nèi)容寫入到該內(nèi)存單元中。使用SWP 可實(shí)現(xiàn)信號(hào)量操作。
??????? 指令格式如下:
??????? SWP{cond}{B} Rd,Rm,[Rn]
??????? 其中,B 為可選后綴,若有B,則交換字節(jié),否則交換32 位字:Rd為數(shù)據(jù)從存儲(chǔ)器加載到的寄存器;Rm 的數(shù)據(jù)用于存儲(chǔ)到存儲(chǔ)器中,若Rm 與Rn 相同,則為寄存器與存儲(chǔ)器內(nèi)容進(jìn)行交換;Rn 為要進(jìn)行數(shù)據(jù)交換的存儲(chǔ)器地址,Rn 不能與Rd 和Rm 相同。
??????? SWP 指令舉例如下:
??????? SWP R1,R1,[R0] ; 將R1 的內(nèi)容與R0 指向的存儲(chǔ)單元的內(nèi)容進(jìn)行交換
??????? SWP R1,R2,,[R0] ; 將R0 指向的存儲(chǔ)單元內(nèi)容讀取一字節(jié)數(shù)據(jù)到R1 中(高24 位清零)
???????????????????????????????????????; 并將R2 的內(nèi)容寫入到該內(nèi)存單元中(最低字節(jié)有效)
??????? 使用SWP 指令可以方便地進(jìn)行信號(hào)量的操作:
??????? 12C_SEM EQU 0x40003000
??????? …
??????? 12C_SEM_WAIT
??????? MOV R0,#0
??????? LDR R0,=12C_SEM
??????? SWP R1,R1,[R0] ?????? ;取出信號(hào)量,并設(shè)置其為0
??????? CMP R1,#0 ?????? ??? ;判斷是否有信號(hào)
??????? BEQ 12C_SEM_WAIT???? ;若沒有信號(hào),則等待
3? ARM 數(shù)據(jù)處理指令
??????? 數(shù)據(jù)處理指令大致可分為3 類;數(shù)據(jù)傳送指令(如MOV、MVN),算術(shù)邏輯運(yùn)算指令(如ADD,SUM,AND),比較指令(如CMP、TST)。數(shù)據(jù)處理指令只能對(duì)寄存器的內(nèi)容進(jìn)行操作。
??????? 所有ARM 數(shù)據(jù)處理指令均可選擇使用S 后綴,以影響狀態(tài)標(biāo)志。比較指令CMP、CMN、TST和TEQ不需要后綴S,它們會(huì)直接影響狀態(tài)標(biāo)志。ARM 數(shù)據(jù)處理指令列于表A-4中。
表A-4? ARM 數(shù)據(jù)處理指令
?????? (1)數(shù)據(jù)傳送指令
??????? MOV
??????? 數(shù)據(jù)傳送指令。將8 位圖立即數(shù)或寄存器(operant2)傳送到目標(biāo)寄存器Rd,可用于移位運(yùn)算等操作。指令格式如下:
??????? MOV{cond}{S} Rd,operand2
??????? MOV 指令舉例如下:
??????? MOV R1#0x10 ;R1=0x10
??????? MOV R0,R1 ;R0=R1
??????? MOVS R3,R1,LSL #2 ;R3=R1<<2,并影響標(biāo)志位
??????? MOV PC,LR?? ;PC=LR ,子程序返回
??????? MVN
??????? 數(shù)據(jù)非傳送指令。將8 位圖立即數(shù)或寄存器(operand2)按位取反后傳送到目標(biāo)寄存器(Rd),因?yàn)槠渚哂腥》垂δ?#xff0c;所以可以裝載范圍更廣的立即數(shù)。指令格式如下:
??????? MVN{cond}{S} Rd,operand2
??????? MVN 指令舉例如下:
??????? MVN R1,#0xFF ;R1=0xFFFFFF00
??????? MVN R1,R2 ;將R2取反,結(jié)果存到R1
??????? (2)算術(shù)邏輯運(yùn)算指令
??????? ADD
??????? 加法運(yùn)算指令。將operand2 數(shù)據(jù)與Rn 的值相加,結(jié)果保存到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
??????? 減法運(yùn)算指令。用寄存器Rn 減去operand2。結(jié)果保存到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,結(jié)果保存到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
??????? 帶進(jìn)位加法指令。將operand2 的數(shù)據(jù)與Rn 的值相加,再加上CPSR 中的C 條件標(biāo)志位。結(jié)果保存到Rd寄存器。指令格式如下:
??????? ADC{cond}{S} Rd,Rn,operand2
??????? ADC 指令舉例如下:
??????? ADDS R0,R0,R2
??????? ADC R1,R1,R3 ;使用ADC 實(shí)現(xiàn)64 位加法,(R1、R0)=(R1、R0)+(R3、R2)
??????? SBC
??????? 帶進(jìn)位減法指令。用寄存器Rn 減去operand2,再減去CPSR中的C 條件標(biāo)志位的非(即若C 標(biāo)志清零,則結(jié)果減去1),結(jié)果保存到Rd 中。指令格式如下:
??????? SCB{cond}{S}Rd,Rn,operand2
??????? SBC 指令舉例如下:
??????? SUBS R0,R0,R2
??????? SBC R1,R1,R3 ;使用SBC 實(shí)現(xiàn)64 位減法,(R1,R0)-(R3,R2)
???????RSC
??????? 帶進(jìn)位逆向減法指令。用寄存器operand2 減去Rn,再減去CPSR中的C 條件標(biāo)志位,結(jié)果保存到Rd 中。指令格式如下:
??????? RSC{cond}{S} Rd,Rn,operand2
??????? RSC 指令舉例如下:
??????? RSBS R2,R0,#0
??????? RSC R3,R1,#0 ;使用RSC 指令實(shí)現(xiàn)求64 位數(shù)值的負(fù)數(shù)
???????AND
??????? 邏輯與操作指令。將operand2 值與寄存器Rn 的值按位作邏輯與操作,結(jié)果保存到Rd 中。指令格式如下:
??????? AND{cond}{S} Rd,Rn,operand2
??????? AND 指令舉例如下:
??????? ANDS R0,R0,#x01 ;R0=R0&0x01,取出最低位數(shù)據(jù)
??????? AND R2,R1,R3 ;R2=R1&R3
??????? ORR
???????邏輯或操作指令。將operand2 的值與寄存器Rn 的值按位作邏輯或操作,結(jié)果保存到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 位數(shù)據(jù)移入到R3 低8 位中
???????EOR
??????? 邏輯異或操作指令。將operand2 的值與寄存器Rn 的值按位作邏輯異或操作,結(jié)果保存到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 進(jìn)行邏輯異或,結(jié)果保存到R0,并影響標(biāo)志位
??????? BIC
??????? 位清除指令。將寄存器Rn 的值與operand2 的值的反碼按位作邏輯與操作,結(jié)果保存到Rd 中。指令格式如下:
??????? BIC{cond}{S}Rd,Rn,operand2
??????? BIC 指令舉例如下:
??????? BIC R1,R1,#0x0F ;將R1 的低4 位清零,其它位不變
??????? BIC R1,R2,R3 ;將拭的反碼和R2 相邏輯與,結(jié)果保存到R1
??????? (3)比較指令
???????CMP
??????? 比較指令。指令使用寄存器Rn 的值減去operand2 的值,根據(jù)操作的結(jié)果更新CPSR中的相應(yīng)條件標(biāo)志位,以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。指令格式如下:
??????? CMP{cond} Rn,operand2
??????? CMP 指令舉例如下:
??????? CMP R1,#10 ;R1 與10 比較,設(shè)置相關(guān)標(biāo)志位
??????? CMP R1,R2 ;R1 與R2 比較,設(shè)置相關(guān)標(biāo)志位
??????? CMP 指令與SUBS 指令的區(qū)別在于CMP 指令不保存運(yùn)算結(jié)果。在進(jìn)行兩個(gè)數(shù)據(jù)大小判斷時(shí),常用CMP 指令及相應(yīng)的條件碼來操作。
???????CMN
??????? 負(fù)數(shù)比較指令。指令使用寄存器Rn 與值加上operand2 的值,根據(jù)操作的結(jié)果更新CPSR 中的相應(yīng)條件標(biāo)志位,以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行,指令格式如下:
??????? CMN{cond} Rn,operand2
??????? CMN R0,#1 ;R0+1,判斷R0 是否為1 的補(bǔ)碼,若是Z 置位
??????? CMN 指令與ADDS 指令的區(qū)別在于CMN 指令不保存運(yùn)算結(jié)果。CMN 指令可用于負(fù)數(shù)比較,比如CMNR0,#1 指令則表示R0 與-1 比較,若R0 為-(即1 的補(bǔ)碼),則Z 置位,否則Z復(fù)位。
??????? TST
??????? 位測(cè)試指令。指令將寄存器Rn 的值與operand2 的值按位作邏輯與操作,根據(jù)操作的結(jié)果更新CPSR 中相應(yīng)的條件標(biāo)志位,以便后面指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。指令格式如下:
??????? TST{cond} Rn,operand2
??????? TST 指令舉例如下:
??????? TST R0,#0x01 ;判斷R0 的最低位是否為0
??????? TST R1,#0x0F ;判斷R1 的低4 位是否為0
??????? TST 指令與ANDS 指令的區(qū)別在于TST4 指令不保存運(yùn)算結(jié)果。TST 指令通常于EQ、NE條件碼配合使用,當(dāng)所有測(cè)試位均為0 時(shí),EQ 有效,而只要有一個(gè)測(cè)試為不為0,則NE 有效。
???????TEQ
??????? 相等測(cè)試指令。指令寄存器Rn 的值與operand2 的值按位作邏輯異或操作,根據(jù)操作的結(jié)果更新CPSR 中相應(yīng)條件標(biāo)志位,以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。指令格式如下:
??????? TEQ{cond} Rn,operand2
??????? TEQ 指令舉例如下:
??????? TEQ R0,R1 ;比較R0 與R1 是否相等(不影響V 位和C 位)
??????? TST 指令與EORS 指令的區(qū)別在于TST 指令不保存運(yùn)算結(jié)果。使用TEQ 進(jìn)行相等測(cè)試,常與EQNE 條件碼配合使用,當(dāng)兩個(gè)數(shù)據(jù)相等時(shí),EQ 有效,否則NE 有效。
??????? (4)乘法指令
??????? ARM7TDMI(-S)具有32×32 乘法指令、32×32乘加指令、32×32 結(jié)果為64 位的乘法指令。表A-5給出全部的ARM 乘法指令。
表A-5? 全部的ARM乘法指令
???????MUL
??????? 32 位乘法指令。指令將Rm 和Rs 中的值相乘,結(jié)果的低32 位保存到Rd 中。指令格式如下:
??????? MUL{cond}{S} Rd,Rm,Rs
??????? MUL 指令舉例如下:
??????? MUL R1,R2,R3 ;R1=R2×R3
??????? MULS R0,R3,R7 ;R0=R3×R7,同時(shí)設(shè)置CPSR 中的N 位和Z 位
???????MLA
??????? 32 位乘加指令。指令將Rm 和Rs 中的值相乘,再將乘積加上第3 個(gè)操作數(shù),結(jié)果的低32 位保存到Rd中。指令格式如下:
??????? MLA{cond}{S} Rd,Rm,Rs,Rn
??????? MLA 指令舉例如下:
??????? MLA R1,R2,R3,R0 ;R1=R2×R3+10
??????? UMULL
??????? 64 位無符號(hào)乘法指令。指令將Rm 和Rs 中的值作無符號(hào)數(shù)相乘,結(jié)果的低32 位保存到RsLo 中,而高32 位保存到RdHi 中。指令格式如下:
??????? UMULL{cond}{S} RdLo,RdHi,Rm,Rs
??????? UMULL 指令舉例如下:
??????? UMULL R0,R1,R5,R8 ;(R1、R0)=R5×R8
??????? UMLAL
??????? 64 位無符號(hào)乘加指令。指令將Rm 和Rs 中的值作無符號(hào)數(shù)相乘,64 位乘積與RdHi、RdLo 相加,結(jié)果的低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 位有符號(hào)乘法指令。指令將Rm 和Rs 中的值作有符號(hào)數(shù)相乘,結(jié)果的低32 位保存到RdLo 中,而高32 位保存到RdHi 中。指令格式如下:
??????? SMULL{cond}{S} RdLo,RdHi,Rm,Rs
??????? SMULL 指令舉例如下:
??????? SMULL R2,R3,R7,R6 ;(R3,R2)=R7×R6
??????? SMLAL
??????? 64 位有符號(hào)乘加指令。指令將Rm 和Rs 中的值作有符號(hào)數(shù)相乘,64 位乘積與RdHi、RdLo,相加,結(jié)果的低32 位保存到RdLo 中,而高32 位保存到RdHi 中。指令格式如下:
??????? SMLAL{cond}{S} RdLo,RdHi,Rm,Rs
??????? SMLAL 指令舉例如下:
??????? SMLAL R2,R3,R7,R6;(R3,R2)=R7×R6+(R3,R2)
4? ARM 跳轉(zhuǎn)指令
??????? 在ARM 中有兩種方式可以實(shí)現(xiàn)程序的跳轉(zhuǎn),一種是使用跳轉(zhuǎn)指令直接跳轉(zhuǎn),另一種則是直接向PC寄存器賦值實(shí)現(xiàn)跳轉(zhuǎn)。跳轉(zhuǎn)指令有跳轉(zhuǎn)指令B,帶鏈接的跳轉(zhuǎn)指令BL帶狀態(tài)切換的跳轉(zhuǎn)指令BX。表A-6給出全部的ARM跳轉(zhuǎn)指令。
表A-6? ARM跳轉(zhuǎn)指令
? ????? B
??????? 跳轉(zhuǎn)指令。跳轉(zhuǎn)到指定的地址執(zhí)行程序。指令格式如下:
??????? B{cond} label
??????? 跳轉(zhuǎn)指令B 舉例如下:
??????? B WAITA ;跳轉(zhuǎn)到WAITA標(biāo)號(hào)處
??????? B 0x1234 ;跳轉(zhuǎn)到絕對(duì)地址0x1234 處
??????? 跳轉(zhuǎn)到指令B 限制在當(dāng)前指令的±32Mb 的范圍內(nèi)。
??????? BL
??????? 帶鏈接的跳轉(zhuǎn)指令。指令將下一條指令的地址拷貝到R14(即LR)鏈接寄存器中,然后跳轉(zhuǎn)到指定地址運(yùn)行程序。指令格式如下:
??????? BL{cond} label
??????? 帶鏈接的跳轉(zhuǎn)指令BL 舉例如下:
??????? BL DELAY
??????? 跳轉(zhuǎn)指令B 限制在當(dāng)前指令的±32MB 的范圍內(nèi)。BL 指令用于子程序調(diào)用。
??????? BX
??????? 帶狀態(tài)切換的跳轉(zhuǎn)指令。跳轉(zhuǎn)到Rm 指定的地址執(zhí)行程序,若Rm 的位[0]為1,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR 中的標(biāo)志T 置位,即把目標(biāo)地址的代碼解釋為Thumb 代碼;若Rm 的位[0]為0,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR 中的標(biāo)志T 復(fù)位,即把目標(biāo)地址的代碼解釋為ARM 代碼。指令格式如下:
??????? BX{cond} Rm
??????? 帶狀態(tài)切換的跳轉(zhuǎn)指令BX舉例如下:
??????? ADRL R0,ThumbFun+1
??????? BX R0 ;跳轉(zhuǎn)到R0指定的地址,并根據(jù)R0 的最低位來切換處理器狀態(tài)
5?? ARM 協(xié)處理器指令
???????ARM 支持協(xié)處理器操作,協(xié)處理器的控制要通過協(xié)處理器命令實(shí)現(xiàn)。表A-7給出全部的ARM協(xié)處理器指令。
表A-7? ARM 協(xié)處理器指令
?????? CDP
??????? 協(xié)處理器數(shù)據(jù)操作指令。ARM 處理器通過CDP 指令通知ARM協(xié)處理器執(zhí)行特定的操作。該操作由協(xié)處理器完成,即對(duì)命令的參數(shù)的解釋與協(xié)處理器有關(guān),指令的使用取決于協(xié)處理器。若協(xié)處理器不能成功地執(zhí)行該操作,將產(chǎn)生未定義指令異常中斷。指令格式如下:
??????? CDP{cond} coproc,opcodel,CRd,CRn,CRm{,opcode2}
??????? 其中: coproc 指令操作的協(xié)處理器名。標(biāo)準(zhǔn)名為pn,n 為0~15。
??????? opcodel 協(xié)處理器的特定操作碼。
??????? CRd 作為目標(biāo)寄存器的協(xié)處理器寄存器。
??????? CRN 存放第1 個(gè)操作數(shù)的協(xié)處理器寄存器。
??????? CRm 存放第2 個(gè)操作數(shù)的協(xié)處理器寄存器。
??????? Opcode2 可選的協(xié)處理器特定操作碼。
??????? CDP 指令舉例如下:
??????? CDP p7,0,c0,c2,c3,0 ;協(xié)處理器7 操作,操作碼為0,可選操作碼為0
??????? CDP p6,1,c3,c4,c5 ;協(xié)處理器操作,操作碼為1
??????? LDC
??????? 協(xié)處理器數(shù)據(jù)讀取指令。LDC 指令從某一連續(xù)的內(nèi)存單元將數(shù)據(jù)讀取到協(xié)處理器的寄存器中。協(xié)處理器數(shù)據(jù)的數(shù)據(jù)的傳送,由協(xié)處理器來控傳送的字?jǐn)?shù)。若協(xié)處理器不能成功地執(zhí)行該操作,將產(chǎn)生未定義指令異常中斷。指令格式如下:
??????? LDC{cond}{L} coproc,CRd,<地址>
??????? 其中: L 可選后綴,指明是長(zhǎng)整數(shù)傳送。
??????? coproc 指令操作的協(xié)處理器名。標(biāo)準(zhǔn)名為pn,n 為0~15
??????? CRd 作為目標(biāo)寄存的協(xié)處理器寄存器。
??????? <地址> 指定的內(nèi)存地址
??????? LDC 指令舉例如下:
??????? LDC p5,c2,[R2,#4];讀取R2+4指向的內(nèi)存單元的數(shù)據(jù),傳送到協(xié)處理器p5的c2寄存器中
??????? LDC p6,c2,[R1] ;讀取是指向的內(nèi)存單元的數(shù)據(jù),傳送到協(xié)處理器p6 的c2 寄存器中
??????? STC
??????? 協(xié)處理器數(shù)據(jù)寫入指令。STC 指令將協(xié)處理器的寄存器數(shù)據(jù)寫入到某一連續(xù)的內(nèi)存單元中。進(jìn)行協(xié)處理器數(shù)據(jù)的數(shù)據(jù)傳送,由協(xié)處理器來控制傳送的字?jǐn)?shù)。若協(xié)處理器不能成功地執(zhí)行該操作,將產(chǎn)生未定義指令異常中斷。指令格式如下:
??????? STC{cond}{L} coproc,CRd,<地址>
??????? 其中: L 可選后綴,指明是長(zhǎng)整數(shù)傳送。
??????? coproc 指令操作的協(xié)處理器名。標(biāo)準(zhǔn)名為pn,n 為0~15
??????? CRd 作為目標(biāo)寄存的協(xié)處理器寄存器。
??????? <地址> 指定的內(nèi)存地址
??????? STC 指令舉例如下:
??????? STC p5,c1,[R0]
??????? STC p5,c1,[Ro,#-0x04]
??????? MCR
??????? ARM 寄存器到協(xié)處理器寄存器的數(shù)據(jù)傳送指令。MCR 指令將ARM 處理器的寄存器中的數(shù)據(jù)傳送到協(xié)處理器的寄存器中。若協(xié)處理器不能成功地執(zhí)行該操作,將產(chǎn)生未定義指令異常中斷。指令格式如下:
??????? MCR{cond}coproc,opcodel,Rd,CRn,CRm{,opcode2}
??????? 其中:coproc 指令操作的協(xié)處理器名。標(biāo)準(zhǔn)名為pn,n 為0~15。
??????? cpcodel 協(xié)處理器的特定操作碼。
??????? CRD 作為目標(biāo)寄存器的協(xié)處理器寄存器。
??????? CRn 存放第1 個(gè)操作數(shù)的協(xié)處理器寄存器
??????? CRm 存放第2 個(gè)操作數(shù)的協(xié)處理器寄存器。
??????? Opcode2 可選的協(xié)處理器特定操作碼。
??????? MCR 指令舉例如下:
??????? MCR p6,2,R7,c1,c2,
??????? MCR P7,0,R1,c3,c2,1,
???????MRC
??????? 協(xié)處理器寄存器到ARM 寄存器到的數(shù)據(jù)傳送指令。MRC 指令將協(xié)處理器寄存器中的數(shù)據(jù)傳送到ARM 處理器的寄存器中。若協(xié)處理器不能成功地執(zhí)行該操作。將產(chǎn)生未定義異常中斷。指令格式如下:
??????? MRC {cond}coproc,opcodel,Rd,CRn,CRm{,opcode2}
??????? 其中:coproc 指令操作的協(xié)處理器名。標(biāo)準(zhǔn)名為pn,n為0~15。
??????? opcodel 協(xié)處理器的特定操作碼。
??????? CRd 作為目標(biāo)寄存器的協(xié)處理器寄存器。
??????? CRn 存放第1 個(gè)操作數(shù)的協(xié)處理器寄存器。
??????? CRm 存放第2 個(gè)操作數(shù)的協(xié)處理器寄存器。
??????? opcode2 可選的協(xié)處理器特定操作碼。
??????? MRC 指令舉例如下:
??????? MRC p5,2,R2,c3,c2
??????? MRC p7,0,R0,c1,c2,1
6?? ARM 雜項(xiàng)指令
??????? 表A-8給出全部的ARM協(xié)處理器指令。
表A-8 ARM雜項(xiàng)指令
?????? SWI
??????? 軟中斷指令。SWI 指令用于產(chǎn)生軟中斷,從而實(shí)現(xiàn)在用戶模式變換到管理模式,CPSR保存到管理模式的SPSR 中,執(zhí)行轉(zhuǎn)移到SWI 向量,在其它模式下也可使用SWI 指令,處理同樣地切換到管理模式。指令格式如下:
??????? SWI{cond} immed_24
??????? 其中:immed_2424 位立即數(shù),值為0~16777215 之間的整數(shù)。
??????? SWI 指令舉例如下:
??????? SWI 0 ;軟中斷,中斷立即數(shù)為0
??????? SWI 0x123456 ;軟中斷,中斷立即數(shù)為0x123456
??????? 使用SWI 指令時(shí),通常使用以下兩種方法進(jìn)行傳遞參數(shù),SWI 異常中斷處理程序就可以提供相關(guān)的服務(wù),這兩種方法均是用戶軟件協(xié)定。SWI 異常中斷處理程序要通過讀取引起軟中斷的SWI 指令,以取得24 位立即數(shù)。
??????? (A)指令24 位的立即數(shù)指定了用戶請(qǐng)求的服務(wù)類型,參數(shù)通過用寄存器傳遞。
??????? MOV R0,#34 ??? ;設(shè)置了功能號(hào)為34
??????? SWI 12 ?????? ;調(diào)用12 號(hào)軟中斷
??????? (B)指令中的24 位立即數(shù)被忽略,用戶請(qǐng)求的服務(wù)類型由寄存器R0 的值決定,參數(shù)通過其它的通用寄存器傳遞。
??????? MOV R0,#12 ??? ;調(diào)用12 號(hào)軟中斷
??????? MOV R1,#34 ??? ;設(shè)置子功能號(hào)為34
??????? SWI 0?????? ;
??????? 在SWI 異常中斷處理程序中,取出SWI 立即數(shù)的步驟為:首先確定引起軟中斷的SWI指令是ARM 指令還時(shí)Thumb 指令,這可通過對(duì)SPSR 訪問得到:然后要取得該SWI 指令的地址,這可通過訪問LR 寄存器得到:接著讀出指令,分解出立即數(shù)。
??????? 讀出SWI 立即數(shù):
??????? T_bit EQU 0x20
??????? SWI_Hander
??????? STMFD SP!,{R0_R3,R12,LR}??? ??? ;現(xiàn)場(chǎng)保護(hù)
??????? MRS R0,SPSR ?????? ??? ??? ??? ;讀取SPSR
??????? STMFD SP!,{R0} ?????? ??? ??? ??? ;保存SPSR
??????? TST R0,#T_bit ?????? ??? ??? ??? ;測(cè)試T 標(biāo)志位
??????? LDRNEH R0,[LR,#-2]??? ??? ??? ??? ;若是Thumb 指令,讀取指令碼(16 位)
??????? BICNE R0,R0,#0xFF00??? ??? ??? ;取得Thumb 指令的8 位立即數(shù)
??????? LDREQ R0,[LR,#-4] ?????? ??? ??? ;若是ARM 指令,讀取指令碼(32 位)
??????? BICNQ R0,R0,#0xFF00000??? ??? ??? ;取得ARM 指令的24 位立即數(shù)
??????? …
??????? LDMFD SP!,{R0-R3,R12,PC}^ ;SWI 異常中斷返回
??????? MRS
??????? 讀狀態(tài)寄存器指令。在ARM 處理器中,只有MRS 指令可以狀態(tài)寄存器CPSR 或SPSR讀出到通用寄存器中。指令格式如下:
??????? MRS{cond} Rd ,psr
??????? 其中: Rd 目標(biāo)寄存器。Rd 不允許為R15。
??????? psr CPSR 或SPSR
??????? MRS指令舉例如下:
??????? MRS R1,CPSR ??? ;將CPSR 狀態(tài)寄存器讀取,保存到R1 中
??????? MRS R2,SPSR ??? ;將SPSR 狀態(tài)寄存器讀取,保存到R2 中
??????? MRS 指令讀取CPSR,可用來判斷ALU 的狀態(tài)標(biāo)志,或IRQ、FIQ 中斷是否允許等;在異常處理程序中,讀SPSR 可知道進(jìn)行異常前的處理器狀態(tài)等。MRS 與MSR 配合使用,實(shí)現(xiàn)CPSR 或SPSR寄存器的讀—修改---寫操作,可用來進(jìn)行處理器模式切換(),允許/禁止IRQ/FIQ 中斷等設(shè)置。另外,進(jìn)程切換或允許異常中斷嵌套時(shí),也需要使用MRS 指令讀取SPSR 狀態(tài)值。保存起來。
??????? 使能IRQ 中斷例程:
??????? ENABLE_IRQ
??????? MRS R0,CPSR
??????? BIC R0。R0,#0x80
??????? MSR CPSR_c,R0
??????? MOV PC,LR
??????? 禁能IRQ 中斷例程:
??????? DISABLE_IRQ
??????? MRS R0,CPSR
??????? ORR R0,R0,#0x80
??????? MSR CPSR_c,R0
??????? MOV PC,LR
??????? MSR
??????? 寫狀態(tài)寄存器指令。在ARM 處理器中。只有MSR 指令可以直接設(shè)置狀態(tài)寄存器CPSR或SPSR。指令格式如下:
??????? MSR{cond} psr_fields,#immed_8r
??????? MSR{cond} psr_fields,Rm
??????? 其中: psr CPSR或SPSR
??????? fields 指定傳送的區(qū)域。Fields 可以是以下的一種或多種(字母必須為小寫):
??????? c 控制域屏蔽字節(jié)(psr[7…0])
??????? x 擴(kuò)展域屏蔽字節(jié)(psr[15…8])
??????? s 狀態(tài)域屏蔽字節(jié)(psr[23?!?6])
??????? f 標(biāo)志域屏蔽字節(jié)(psr[31…24])
??????? immed_8r 要傳送到狀態(tài)寄存器指定域的立即數(shù),8 位。
??????? Rm 要傳送到狀態(tài)寄存器指定域的數(shù)據(jù)的源寄存器。
??????? MSR 指令舉例如下:
??????? MSR CPSR_c,#0xD3 ;CPSR[7…0]=0xD3,即切換到管理模式。
??????? MSR CPSR_cxsf,R3 ;CPSR=R3
??????? 只有在特權(quán)模式下才能修改狀態(tài)寄存器。
??????? 程序中不能通過MSR 指令直接修改CPSR 中的T 控制位來實(shí)現(xiàn)ARM 狀態(tài)/Thumb 狀態(tài)的切換,必須使用BX 指令完成處理器狀態(tài)的切換(因?yàn)锽X 指令屬轉(zhuǎn)移指令,它會(huì)打斷流水線狀態(tài),實(shí)現(xiàn)處理器狀態(tài)切換)。MRS 與MSR 配合使用,實(shí)現(xiàn)CPSR 或SPSR 寄存器的讀-修改-寫操作,可用來進(jìn)行處理器模式切換、允許/禁止IRQ/FIQ 中斷等設(shè)置。
??????? 堆棧指令實(shí)始化例程:
??????? INITSTACK
??????? MOV R0,LR ;保存返回地址
??????? ;設(shè)置管理模式堆棧
??????? MSR CPSR_c,#0xD3
??????? LDR SP,StackSvc
??????????????????????;設(shè)置中斷模式堆棧
??????? MSR CPSR_c,#0xD2
??????? LDR SP,StackIrq
??????? …
7?? ARM 偽指令
??????? ARM 偽指令不是ARM 指令集中的指令,只是為了編程方便編譯器定義了偽指令,使用時(shí)可以像其它ARM 指令一樣使用,但在編譯時(shí)這些指令將被等效的ARM 指令代替。ARM 偽指令有四條,分別為ADR 偽指令、ADRL 偽指令、LDR 偽指令和NOP偽指令。
??????? ADR
???????小范圍的地址讀取偽指令。ADR 指令將基于PC 相對(duì)偏移的地址值讀取到寄存器中。在匯編編譯源程序時(shí),ADR 偽指令被編譯器替換成一條合適的指令。通常,編譯器用一條ADD 指令或SUB 指令來實(shí)現(xiàn)該ADR偽指令的功能,若不能用一條指令實(shí)現(xiàn),則產(chǎn)生錯(cuò)誤,編譯失敗。
??????? ADR 偽指令格式如下:
??????? ADR{cond} register,exper
??????? 其中:register 加載的目標(biāo)寄存器。
??????? exper 地址表達(dá)式。當(dāng)?shù)刂分凳欠亲值佚R時(shí),取值范圍-255~255 字節(jié)之間;當(dāng)?shù)刂肥亲謱?duì)齊時(shí),取值范圍-1020~1020 字節(jié)之間。
??????? 對(duì)于基于PC 相對(duì)偏移的地址值時(shí),給定范圍是相對(duì)當(dāng)前指令地址后兩個(gè)字處(因?yàn)锳RM7TDMI 為三級(jí)流水線)。
??????? ADR 偽指令舉例如下:
??????? LOOP MOV R1, #0xF0
??????? …
??????? ADR R2, LOOP ?????? ;將LOOP 的地址放入R2
??????? ADR R3, LOOP+4
??????? 可以用ADR 加載地址,實(shí)現(xiàn)查表:
??????? …
??????? ADR R0,DISP_TAB ??? ;加載轉(zhuǎn)換表地址
??????? LDRB R1,[R0,R2] ??? ;使用R2 作為參數(shù),進(jìn)行查表
??????? …
??????? DISP_TAB
??????? DCB0Xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
??????? ADRL
??????? 中等范圍的地址讀取偽指令。ADRL 指令將基于PC 相對(duì)偏移的地址值或基于寄存器相對(duì)偏移的地址值讀取到寄存器中,比ADR 偽指令可以讀取更大范圍的地址。在匯編編譯源程序時(shí),ADRL 偽指令被編譯器替換成兩個(gè)條合適的指令。若不能用兩條指令實(shí)現(xiàn)ADRL 偽指令功能,則產(chǎn)生錯(cuò)誤,編譯失敗。ADRL 偽指令格式如下:
??????? ADR{cond} register,exper
??????? 其中:register 加載的目標(biāo)寄存器。
??????? expr 地址表達(dá)式。當(dāng)?shù)刂分凳欠亲謱?duì)齊時(shí),取范圍-64K~64K 字節(jié)之間;當(dāng)?shù)刂分凳亲謱?duì)齊時(shí),取值范圍-256K~256K 字節(jié)之間。
??????? ADRL 偽指令舉例如下:
??????? ADRL R0,DATA_BUF
??????? …
??????? ADRL R1 DATA_BUF+80
??????? …
??????? DATA_BUF
??????? SPACE 100 ??? ;定義100 字節(jié)緩沖區(qū)
??????? 可以且用ADRL 加載地址,實(shí)現(xiàn)程序跳轉(zhuǎn),中等范圍地址的加載:
??????? …
??????? ADR LR,RETURNI ?????? ??? ;設(shè)置返回地址
??????? ADRL R1Thumb_Sub+1??? ??? ;取得了Thumb子程序入口地址,且R1 的0 位置1
??????? BX R1 ?????? ??? ??? ??? ;調(diào)用Thumb 子程序,并切換處理器狀態(tài)
??????? RETURNI
??????? …
??????? CODE16
??????? Thumb_Sub
??????? MOV R1,#10
??????? …
??????? LDR
??????? 大范圍的地址讀取偽指令。LDR 偽指令用于加載32 位的立即數(shù)或一個(gè)地址值到指定寄存器。在匯編編譯源程序時(shí),LDR 偽指令被編譯器替換成一條合適的指令。若加載的常數(shù)未超出MOV 或MVN 的范圍,則使用MOV 或MVN 指令代替該LDR 偽指令,否則匯編器將常量放入字池,并使用一條程序相對(duì)偏移的LDR 指令從文字池讀出常量。LDR 偽指令格式如下:
??????? LDR{cond} register,=expr/label_expr
??????? 其中:register 加載的目標(biāo)寄存器
??????? expr 32 位立即數(shù)。
??????? label_expr 基于PC 的地址表達(dá)式或外部表達(dá)式。
??????? LADR 偽指令舉例如下:。
??????? LDR R0,=0x123456 ?????? ;加載32 位立即數(shù)0x12345678
??????? LDR R0,=DATA_BUF+60??? ;加載DATA_BUF 地址+60
??????? …
??????? LTORG ?????? ??? ??? ??? ;聲明文字池
??????? 偽指令LDR 常用于加載芯片外圍功能部件的寄存器地址(32 位立即數(shù)),以實(shí)現(xiàn)各種控制操作加載32 位立即數(shù):
??????? …
??????? LDR R0,=IOPIN ;加載GPIO 寄存器IOPIN 的地址
??????? LDR R1,[R0] ;讀取IOPIN 寄存器的值
??????? …
??????? LDR R0,=IOSET
??????? LDR R1,=0x00500500
??????? STR R1,[R0] ;IOSET=0x00500500
??????? …
??????? 從PC 到文字池的偏移量必須小于4KB。與ARM 指令的LDR 相比,偽指令的LDR 的參數(shù)有“=”號(hào)
???????NOP
??????? 空操作偽指令。NOP 偽指令在匯編時(shí)將會(huì)被代替成ARM 中的空操作,比如可能為“MOV? R0, R0”指令等,NOP 偽指令格式如下:
??????? NOP
??????? NOP
??????? NOP
??????? NOP
??????? SUBS R1, R1, #1
??????? BNE DELAY1
??????? …
?
?
總結(jié)
- 上一篇: kuangbin棋盘问题
- 下一篇: 下周开幕!给深圳的嵌入式和电子工程师准备