介紹 ARM指令集、Thumb指令集,以及各類指令對應的尋址方式,通過對本章的閱讀,希望讀者能了解ARM微處理器所支援的指令集及具體的使用方法。
本章的主要内容有:
- ARM指令集、Thumb指令集概述。
- ARM指令集的分類與具體應用。
- Thumb指令集簡介及應用場合。
3.1 ARM微處理器的指令集概述
3.1.1 ARM微處理器的指令的分類與格式
ARM微處理器的指令集是加載/存儲型的,也即指令集僅能處理寄存器中的資料,而且處理結果都要放回寄存器中,而對系統存儲器的通路則需要通過專門的加載/存儲指令來完成。
ARM微處理器的指令集可以分為跳轉指令、資料處理指令、程式狀态寄存器(PSR)處理指令、加載/存儲指令、協處理器指令和異常産生指令六大類,具體的指令及功能如表3-1所示(表中指令為基本ARM指令,不包括派生的ARM指令)。
表3-1 ARM指令及功能描述
助記符 | 指令功能描述 |
ADC | 帶進位加法指令 |
ADD | 加法指令 |
AND | 邏輯與指令 |
B | 跳轉指令 |
BIC | 位清零指令 |
BL | 帶傳回的跳轉指令 |
BLX | 帶傳回和狀态切換的跳轉指令 |
BX | 帶狀态切換的跳轉指令 |
CDP | 協處理器資料操作指令 |
CMN | 比較反值指令 |
CMP | 比較指令 |
EOR | 異或指令 |
LDC | 存儲器到協處理器的資料傳輸指令 |
LDM | 加載多個寄存器指令 |
LDR | 存儲器到寄存器的資料傳輸指令 |
MCR | 從ARM寄存器到協處理器寄存器的資料傳輸指令 |
MLA | 乘加運算指令 |
MOV | 資料傳送指令 |
MRC | 從協處理器寄存器到ARM寄存器的資料傳輸指令 |
MRS | 傳送CPSR或SPSR的内容到通用寄存器指令 |
MSR | 傳送通用寄存器到CPSR或SPSR的指令 |
MUL | 32位乘法指令 |
MLA | 32位乘加指令 |
MVN | 資料取反傳送指令 |
ORR | 邏輯或指令 |
RSB | 逆向減法指令 |
RSC | 帶借位的逆向減法指令 |
SBC | 帶借位減法指令 |
STC | 協處理器寄存器寫入存儲器指令 |
STM | 批量記憶體字寫入指令 |
STR | 寄存器到存儲器的資料傳輸指令 |
SUB | 減法指令 |
SWI | 軟體中斷指令 |
SWP | 交換指令 |
TEQ | 相等測試指令 |
TST | 位測試指令 |
3.1.2 指令的條件域
當處理器工作在ARM狀态時,幾乎所有的指令均根據CPSR中條件碼的狀态和指令的條件域有條件的執行。當指令的執行條件滿足時,指令被執行,否則指令被忽略。
每一條ARM指令包含4位的條件碼,位于指令的最高4位[31:28]。條件碼共有16種,每種條件碼可用兩個字元表示,這兩個字元可以添加在指令助記符的後面和指令同時使用。例如,跳轉指令B可以加上字尾EQ變為BEQ表示“相等則跳轉”,即當CPSR中的Z标志置位時發生跳轉。
在16種條件标志碼中,隻有15種可以使用,如表3-2所示,第16種(1111)為系統保留,暫時不能使用。
表3-2 指令的條件碼
條件碼 | 助記符字尾 | 标 志 | 含 義 |
0000 | EQ | Z置位 | 相等 |
0001 | NE | Z清零 | 不相等 |
0010 | CS | C置位 | 無符号數大于或等于 |
0011 | CC | C清零 | 無符号數小于 |
0100 | MI | N置位 | 負數 |
0101 | PL | N清零 | 正數或零 |
0110 | VS | V置位 | 溢出 |
0111 | VC | V清零 | 未溢出 |
1000 | HI | C置位Z清零 | 無符号數大于 |
1001 | LS | C清零Z置位 | 無符号數小于或等于 |
1010 | GE | N等于V | 帶符号數大于或等于 |
1011 | LT | N不等于V | 帶符号數小于 |
1100 | GT | Z清零且(N等于V) | 帶符号數大于 |
1101 | LE | Z置位或(N不等于V) | 帶符号數小于或等于 |
1110 | AL | 忽略 | 無條件執行 |
3.2 ARM指令的尋址方式
所謂尋址方式就是處理器根據指令中給出的位址資訊來尋找實體位址的方式。目前ARM指令系統支援如下幾種常見的尋址方式。
3.2.1 立即尋址
立即尋址也叫立即數尋址,這是一種特殊的尋址方式,操作數本身就在指令中給出,隻要取出指令也就取到了操作數。這個操作數被稱為立即數,對應的尋址方式也就叫做立即尋址。例如以下指令:
ADD R0,R0,#1 ;R0← R0+1
ADD R0,R0,#0x3f ;R0← R0+0x3f
在以上兩條指令中,第二個源操作數即為立即數,要求以“#”為字首,對于以十六進制表示的立即數,還要求在“#”後加上“0x”或“&”。
3.2.2 寄存器尋址
寄存器尋址就是利用寄存器中的數值作為操作數,這種尋址方式是各類微處理器經常采用的一種方式,也是一種執行效率較高的尋址方式。以下指令:
ADD R0,R1,R2 ;R0← R1+R2
該指令的執行效果是将寄存器R1和R2的内容相加,其結果存放在寄存器R0中。
3.2.2 寄存器間接尋址
寄存器間接尋址就是以寄存器中的值作為操作數的位址,而操作數本身存放在存儲器中。例如以下指令:
ADD R0,R1,[R2] ;R0← R1+[R2]
LDR R0,[R1] ;R0← [R1]
STR R0,[R1] ;[R1]←R0
在第一條指令中,以寄存器R2的值作為操作數的位址,在存儲器中取得一個操作數後與R1相加,結果存入寄存器R0中。
第二條指令将以R1的值為位址的存儲器中的資料傳送到R0中。
第三條指令将R0的值傳送到以R1的值為位址的存儲器中。
3.2.3 基址變址尋址
基址變址尋址就是将寄存器(該寄存器一般稱作基址寄存器)的内容與指令中給出的位址偏移量相加,進而得到一個操作數的有效位址。變址尋址方式常用于通路某基位址附近的位址單元。采用變址尋址方式的指令常見有以下幾種形式,如下所示:
LDR R0,[R1,#4] ;R0← [R1+4]
LDR R0,[R1,#4]! ;R0← [R1+4]、R1←R1+4
LDR R0,[R1] ,#4 ;R0← [R1]、R1←R1+4
LDR R0,[R1,R2] ;R0← [R1+R2]
在第一條指令中,将寄存器R1的内容加上4形成操作數的有效位址,進而取得操作數存入寄存器R0中。
在第二條指令中,将寄存器R1的内容加上4形成操作數的有效位址,進而取得操作數存入寄存器R0中,然後,R1的内容自增4個位元組。
在第三條指令中,以寄存器R1的内容作為操作數的有效位址,進而取得操作數存入寄存器R0中,然後,R1的内容自增4個位元組。
在第四條指令中,将寄存器R1的内容加上寄存器R2的内容形成操作數的有效位址,進而取得操作數存入寄存器R0中。
3.2.4 多寄存器尋址
采用多寄存器尋址方式,一條指令可以完成多個寄存器值的傳送。這種尋址方式可以用一條指令完成傳送最多16個通用寄存器的值。以下指令:
LDMIA R0,{R1,R2,R3,R4} ;R1← [R0]
;R2← [R0+4]
;R3← [R0+8]
;R4← [R0+12]
該指令的字尾IA表示在每次執行完加載/存儲操作後,R0按字長度增加,是以,指令可将連續存儲單元的值傳送到R1~R4。
3.2.5 相對尋址
與基址變址尋址方式相類似,相對尋址以程式計數器PC的目前值為基位址,指令中的位址标号作為偏移量,将兩者相加之後得到操作數的有效位址。以下程式段完成子程式的調用和傳回,跳轉指令BL采用了相對尋址方式:
BL NEXT ;跳轉到子程式NEXT處執行
……
NEXT
……
MOV PC,LR ;從子程式傳回
3.2.6 堆棧尋址
堆棧是一種資料結構,按先進後出(First In Last Out,FILO)的方式工作,使用一個稱作堆棧指針的專用寄存器訓示目前的操作位置,堆棧指針總是指向棧頂。
當堆棧指針指向最後壓入堆棧的資料時,稱為滿堆棧(Full Stack),而當堆棧指針指向下一個将要放入資料的空位置時,稱為空堆棧(Empty Stack)。
同時,根據堆棧的生成方式,又可以分為遞增堆棧(Ascending Stack)和遞減堆棧(Decending Stack),當堆棧由低位址向高位址生成時,稱為遞增堆棧,當堆棧由高位址向低位址生成時,稱為遞減堆棧。這樣就有四種類型的堆棧工作方式,ARM微處理器支援這四種類型的堆棧工作方式,即:
- 滿遞增堆棧:堆棧指針指向最後壓入的資料,且由低位址向高位址生成。
- 滿遞減堆棧:堆棧指針指向最後壓入的資料,且由高位址向低位址生成。
- 空遞增堆棧:堆棧指針指向下一個将要放入資料的空位置,且由低位址向高位址生成。
- 空遞減堆棧:堆棧指針指向下一個将要放入資料的空位置,且由高位址向低位址生成。
3.3 ARM指令集
本節對ARM指令集的六大類指令進行詳細的描述。
3.3.1 跳轉指令
跳轉指令用于實作程式流程的跳轉,在ARM程式中有兩種方法可以實作程式流程的跳轉:
— 使用專門的跳轉指令。
— 直接向程式計數器PC寫入跳轉位址值。
通過向程式計數器PC寫入跳轉位址值,可以實作在4GB的位址空間中的任意跳轉,在跳轉之前結合使用
MOV LR,PC
等類似指令,可以儲存将來的傳回位址值,進而實作在4GB連續的線性位址空間的子程式調用。
ARM指令集中的跳轉指令可以完成從目前指令向前或向後的32MB的位址空間的跳轉,包括以下4條指令:
— B 跳轉指令
— BL 帶傳回的跳轉指令
— BLX 帶傳回和狀态切換的跳轉指令
— BX 帶狀态切換的跳轉指令
1、 B指令
B指令的格式為:
B{條件} 目标位址
B指令是最簡單的跳轉指令。一旦遇到一個 B 指令,ARM 處理器将立即跳轉到給定的目标位址,從那裡繼續執行。注意存儲在跳轉指令中的實際值是相對目前PC值的一個偏移量,而不是一個絕對位址,它的值由彙編器來計算(參考尋址方式中的相對尋址)。它是 24 位有符号數,左移兩位後有符号擴充為 32 位,表示的有效偏移為 26 位(前後32MB的位址空間)。以下指令:
B Label ;程式無條件跳轉到标号Label處執行
CMP R1,#0 ;當CPSR寄存器中的Z條件碼置位時,程式跳轉到标号Label處執行
BEQ Label
2、 BL指令
BL指令的格式為:
BL{條件} 目标位址
BL 是另一個跳轉指令,但跳轉之前,會在寄存器R14中儲存PC的目前内容,是以,可以通過将R14 的内容重新加載到PC中,來傳回到跳轉指令之後的那個指令處執行。該指令是實作子程式調用的一個基本但常用的手段。以下指令:
BL Label ;當程式無條件跳轉到标号Label處執行時,同時将目前的PC值儲存到R14中
3、 BLX指令
BLX指令的格式為:
BLX 目标位址
BLX指令從ARM指令集跳轉到指令中所指定的目标位址,并将處理器的工作狀态有ARM狀态切換到Thumb狀态,該指令同時将 PC的目前内容儲存到寄存器R14中。是以,當子程式使用Thumb指令集,而調用者使用ARM指令集時,可以通過BLX指令實作子程式的調用和處理器工作狀态的切換。同時,子程式的傳回可以通過将寄存器R14值複制到PC中來完成。
4、 BX指令
BX指令的格式為:
BX{條件} 目标位址
BX指令跳轉到指令中所指定的目标位址,目标位址處的指令既可以是ARM指令,也可以是Thumb指令。
3.3.2 資料處理指令
資料處理指令可分為資料傳送指令、算術邏輯運算指令和比較指令等。
資料傳送指令用于在寄存器和存儲器之間進行資料的雙向傳輸。
算術邏輯運算指令完成常用的算術與邏輯的運算,該類指令不但将運算結果儲存在目的寄存器中,同時更新CPSR中的相應條件标志位。
比較指令不儲存運算結果,隻更新 CPSR中相應的條件标志位。
資料處理指令包括:
— MOV 資料傳送指令
— MVN 資料取反傳送指令
— CMP 比較指令
— CMN 反值比較指令
— TST 位測試指令
— TEQ 相等測試指令
— ADD 加法指令
— ADC 帶進位加法指令
— SUB 減法指令
— SBC 帶借位減法指令
— RSB 逆向減法指令
— RSC 帶借位的逆向減法指令
— AND 邏輯與指令
— ORR 邏輯或指令
— EOR 邏輯異或指令
— BIC 位清除指令
1、 MOV指令
MOV指令的格式為:
MOV{條件}{S} 目的寄存器,源操作數
MOV指令可完成從另一個寄存器、被移位的寄存器或将一個立即數加載到目的寄存器。其中S選項決定指令的操作是否影響CPSR中條件标志位的值,當沒有S時指令不更新CPSR中條件标志位的值。
指令示例:
MOV R1,R0 ;将寄存器R0的值傳送到寄存器R1
MOV PC,R14 ;将寄存器R14的值傳送到PC,常用于子程式傳回
MOV R1,R0,LSL#3 ;将寄存器R0的值左移3位後傳送到R1
2、 MVN指令
MVN指令的格式為:
MVN{條件}{S} 目的寄存器,源操作數
MVN指令可完成從另一個寄存器、被移位的寄存器、或将一個立即數加載到目的寄存器。與MOV指令不同之處是在傳送之前按位被取反了,即把一個被取反的值傳送到目的寄存器中。其中 S決定指令的操作是否影響CPSR中條件标志位的值,當沒有S時指令不更新CPSR中條件标志位的值。
指令示例:
MVN R0,#0 ;将立即數0取反傳送到寄存器R0中,完成後R0=-1
3、 CMP指令
CMP指令的格式為:
CMP{條件} 操作數1,操作數2
CMP指令用于把一個寄存器的内容和另一個寄存器的内容或立即數進行比較,同時更新 CPSR中條件标志位的值。該指令進行一次減法運算,但不存儲結果,隻更改條件标志位。标志位表示的是操作數1與操作數2的關系(大、小、相等),例如,當操作數1大于操作操作數2,則此後的有GT 字尾的指令将可以執行。
指令示例:
CMP R1,R0 ;将寄存器R1的值與寄存器R0的值相減,并根據結果設定CPSR的标志位
CMP R1,#100 ;将寄存器R1的值與立即數100相減,并根據結果設定CPSR的标志位
4、 CMN指令
CMN指令的格式為:
CMN{條件} 操作數1,操作數2
CMN指令用于把一個寄存器的内容和另一個寄存器的内容或立即數取反後進行比較,同時更新 CPSR中條件标志位的值。該指令實際完成操作數1和操作數2相加,并根據結果更改條件标志位。
指令示例:
CMN R1,R0 ;将寄存器R1的值與寄存器R0的值相加,并根據結果設定CPSR的标志位
CMN R1,#100 ;将寄存器R1的值與立即數100相加,并根據結果設定CPSR的标志位
5、 TST指令
TST指令的格式為:
TST{條件} 操作數1,操作數2
TST指令用于把一個寄存器的内容和另一個寄存器的内容或立即數進行按位的與運算,并根據運算結果更新CPSR中條件标志位的值。操作數1是要測試的資料,而操作數2是一個位掩碼,該指令一般用來檢測是否設定了特定的位。
指令示例:
TST R1,#%1 ;用于測試在寄存器R1中是否設定了最低位(%表示二進制數)
TST R1,#0xffe ;将寄存器R1的值與立即數0xffe按位與,并根據結果設定CPSR的标志位
6、 TEQ指令
TEQ指令的格式為:
TEQ{條件} 操作數1,操作數2
TEQ指令用于把一個寄存器的内容和另一個寄存器的内容或立即數進行按位的異或運算,并根據運算結果更新CPSR中條件标志位的值。該指令通常用于比較操作數1和操作數2是否相等。
指令示例:
TEQ R1,R2 ;将寄存器R1的值與寄存器R2的值按位異或,并根據結果設定CPSR的标志位
7、 ADD指令
ADD指令的格式為:
ADD{條件}{S} 目的寄存器,操作數1,操作數2
ADD指令用于把兩個操作數相加,并将結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。
指令示例:
ADD R0,R1,R2 ; R0 = R1 + R2
ADD R0,R1,#256 ; R0 = R1 + 256
ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3<< 1)
8、 ADC指令
ADC指令的格式為:
ADC{條件}{S} 目的寄存器,操作數1,操作數2
ADC指令用于把兩個操作數相加,再加上 CPSR中的C條件标志位的值,并将結果存放到目的寄存器中。它使用一個進位标志位,這樣就可以做比32位大的數的加法,注意不要忘記設定S字尾來更改進位标志。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。
以下指令序列完成兩個 128位數的加法,第一個數由高到低存放在寄存器R7~R4,第二個數由高到低存放在寄存器R11~R8,運算結果由高到低存放在寄存器R3~R0:
ADDS R0,R4,R8 ; 加低端的字
ADCS R1,R5,R9 ; 加第二個字,帶進位
ADCS R2,R6,R10 ; 加第三個字,帶進位
ADC R3,R7,R11 ; 加第四個字,帶進位
9、 SUB指令
SUB指令的格式為:
SUB{條件}{S} 目的寄存器,操作數1,操作數2
SUB指令用于把操作數1減去操作數2,并将結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令可用于有符号數或無符号數的減法運算。
指令示例:
SUB R0,R1,R2 ; R0 = R1 - R2
SUB R0,R1,#256 ; R0 = R1 - 256
SUB R0,R2,R3,LSL#1 ; R0 = R2 - (R3<< 1)
10、SBC指令
SBC指令的格式為:
SBC{條件}{S} 目的寄存器,操作數1,操作數2
SBC指令用于把操作數1減去操作數2,再減去 CPSR中的C條件标志位的反碼,并将結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令使用進位标志來表示借位,這樣就可以做大于32位的減法,注意不要忘記設定 S字尾來更改進位标志。該指令可用于有符号數或無符号數的減法運算。
指令示例:
SUBS R0,R1,R2 ; R0 = R1 - R2 - !C,并根據結果設定CPSR的進位标志位
11、RSB指令
RSB指令的格式為:
RSB{條件}{S} 目的寄存器,操作數1,操作數2
RSB指令稱為逆向減法指令,用于把操作數2減去操作數1,并将結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令可用于有符号數或無符号數的減法運算。
指令示例:
RSB R0,R1,R2 ; R0 = R2 – R1
RSB R0,R1,#256 ; R0 = 256 – R1
RSB R0,R2,R3,LSL#1 ; R0 = (R3 << 1)- R2
12、RSC指令
RSC指令的格式為:
RSC{條件}{S} 目的寄存器,操作數1,操作數2
RSC指令用于把操作數2減去操作數1,再減去 CPSR中的C條件标志位的反碼,并将結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令使用進位标志來表示借位,這樣就可以做大于32位的減法,注意不要忘記設定 S字尾來更改進位标志。該指令可用于有符号數或無符号數的減法運算。
指令示例:
RSC R0,R1,R2 ; R0 = R2 – R1 - !C
13、AND指令
AND指令的格式為:
AND{條件}{S} 目的寄存器,操作數1,操作數2
AND指令用于在兩個操作數上進行邏輯與運算,并把結果放置到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令常用于屏蔽操作數1的某些位。
指令示例:
AND R0,R0,#3 ; 該指令保持R0的0、1位,其餘位清零。
14、ORR指令
ORR指令的格式為:
ORR{條件}{S} 目的寄存器,操作數1,操作數2
ORR指令用于在兩個操作數上進行邏輯或運算,并把結果放置到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令常用于設定操作數1的某些位。
指令示例:
ORR R0,R0,#3 ; 該指令設定R0的0、1位,其餘位保持不變。
15、EOR指令
EOR指令的格式為:
EOR{條件}{S} 目的寄存器,操作數1,操作數2
EOR指令用于在兩個操作數上進行邏輯異或運算,并把結果放置到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。該指令常用于反轉操作數1的某些位。
指令示例:
EOR R0,R0,#3 ; 該指令反轉R0的0、1位,其餘位保持不變。
16、BIC指令
BIC指令的格式為:
BIC{條件}{S} 目的寄存器,操作數1,操作數2
BIC指令用于清除操作數1的某些位,并把結果放置到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。操作數2為32位的掩碼,如果在掩碼中設定了某一位,則清除這一位。未設定的掩碼位保持不變。
指令示例:
BIC R0,R0,#%1011 ; 該指令清除 R0 中的位 0、1、和 3,其餘的位保持不變。
3.3.3 乘法指令與乘加指令
ARM微處理器支援的乘法指令與乘加指令共有6條,可分為運算結果為32位和運算結果為64位兩類,與前面的資料處理指令不同,指令中的所有操作數、目的寄存器必須為通用寄存器,不能對操作數使用立即數或被移位的寄存器,同時,目的寄存器和操作數1必須是不同的寄存器。
乘法指令與乘加指令共有以下6條:
— MUL 32位乘法指令
— MLA 32位乘加指令
— SMULL 64位有符号數乘法指令
— SMLAL 64位有符号數乘加指令
— UMULL 64位無符号數乘法指令
— UMLAL 64位無符号數乘加指令
1、 MUL指令
MUL指令的格式為:
MUL{條件}{S} 目的寄存器,操作數1,操作數2
MUL指令完成将操作數1與操作數2的乘法運算,并把結果放置到目的寄存器中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的有符号數或無符号數。
指令示例:
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同時設定CPSR中的相關條件标志位
2、 MLA指令
MLA指令的格式為:
MLA{條件}{S} 目的寄存器,操作數1,操作數2,操作數3
MLA指令完成将操作數1與操作數2的乘法運算,再将乘積加上操作數3,并把結果放置到目的寄存器中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的有符号數或無符号數。
指令示例:
MLA R0,R1,R2,R3 ;R0 = R1 × R2 + R3
MLAS R0,R1,R2,R3 ;R0 = R1 × R2 + R3,同時設定CPSR中的相關條件标志位
3、 SMULL指令
SMULL指令的格式為:
SMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操作數1,操作數2
SMULL指令完成将操作數1與操作數2的乘法運算,并把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的有符号數。
指令示例:
SMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
4、 SMLAL指令
SMLAL指令的格式為:
SMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操作數1,操作數2
SMLAL指令完成将操作數1與操作數2的乘法運算,并把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的有符号數。
對于目的寄存器 Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對于目的寄存器 High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
指令示例:
SMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
5、 UMULL指令
UMULL指令的格式為:
UMULL{條件}{S} 目的寄存器Low,目的寄存器低High,操作數1,操作數2
UMULL指令完成将操作數1與操作數2的乘法運算,并把結果的低32位放置到目的寄存器Low中,結果的高32位放置到目的寄存器High中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的無符号數。
指令示例:
UMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
6、 UMLAL指令
UMLAL指令的格式為:
UMLAL{條件}{S} 目的寄存器Low,目的寄存器低High,操作數1,操作數2
UMLAL指令完成将操作數1與操作數2的乘法運算,并把結果的低32位同目的寄存器Low中的值相加後又放置到目的寄存器Low中,結果的高32位同目的寄存器High中的值相加後又放置到目的寄存器High中,同時可以根據運算結果設定CPSR中相應的條件标志位。其中,操作數1和操作數2均為32位的無符号數。
對于目的寄存器 Low,在指令執行前存放64位加數的低32位,指令執行後存放結果的低32位。
對于目的寄存器 High,在指令執行前存放64位加數的高32位,指令執行後存放結果的高32位。
指令示例:
UMLAL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1
3.3.4 程式狀态寄存器通路指令
ARM微處理器支援程式狀态寄存器通路指令,用于在程式狀态寄存器和通用寄存器之間傳送資料,程式狀态寄存器通路指令包括以下兩條:
— MRS 程式狀态寄存器到通用寄存器的資料傳送指令
— MSR 通用寄存器到程式狀态寄存器的資料傳送指令
1、 MRS指令
MRS指令的格式為:
MRS{條件} 通用寄存器,程式狀态寄存器(CPSR或SPSR)
MRS指令用于将程式狀态寄存器的内容傳送到通用寄存器中。該指令一般用在以下幾種情況:
- 當需要改變程式狀态寄存器的内容時,可用MRS将程式狀态寄存器的内容讀入通用寄存器,修改後再寫回程式狀态寄存器。
- 當在異常處理或程序切換時,需要儲存程式狀态寄存器的值,可先用該指令讀出程式狀态寄存器的值,然後儲存。
指令示例:
MRS R0,CPSR ;傳送CPSR的内容到R0
MRS R0,SPSR ;傳送SPSR的内容到R0
2、 MSR指令
MSR指令的格式為:
MSR{條件} 程式狀态寄存器(CPSR或SPSR)_<域>,操作數
MSR指令用于将操作數的内容傳送到程式狀态寄存器的特定域中。其中,操作數可以為通用寄存器或立即數。<域>用于設定程式狀态寄存器中需要操作的位,32位的程式狀态寄存器可分為4個域:
位 [31:24]為條件标志位域,用f表示;
位 [23:16]為狀态位域,用s表示;
位 [15:8]為擴充位域,用x表示;
位 [7:0]為控制位域,用c表示;
該指令通常用于恢複或改變程式狀态寄存器的内容,在使用時,一般要在 MSR指令中指明将要操作的域。
指令示例:
MSR CPSR,R0 ;傳送R0的内容到CPSR
MSR SPSR,R0 ;傳送R0的内容到SPSR
MSR CPSR_c,R0 ;傳送R0的内容到SPSR,但僅僅修改CPSR中的控制位域
3.3.5 加載/存儲指令
ARM微處理器支援加載/存儲指令用于在寄存器和存儲器之間傳送資料,加載指令用于将存儲器中的資料傳送到寄存器,存儲指令則完成相反的操作。常用的加載存儲指令如下:
— LDR 字資料加載指令
— LDRB 位元組資料加載指令
— LDRH 半字資料加載指令
— STR 字資料存儲指令
— STRB 位元組資料存儲指令
— STRH 半字資料存儲指令
1、LDR指令
LDR指令的格式為:
LDR{條件} 目的寄存器,<存儲器位址>
LDR指令用于從存儲器中将一個32位的字資料傳送到目的寄存器中。該指令通常用于從存儲器中讀取32位的字資料到通用寄存器,然後對資料進行處理。當程式計數器PC作為目的寄存器時,指令從存儲器中讀取的字資料被當作目的位址,進而可以實作程式流程的跳轉。該指令在程式設計中比較常用,且尋址方式靈活多樣,請讀者認真掌握。
指令示例:
LDR R0,[R1] ;将存儲器位址為R1的字資料讀入寄存器R0。
LDR R0,[R1,R2] ;将存儲器位址為R1+R2的字資料讀入寄存器R0。
LDR R0,[R1,#8] ;将存儲器位址為R1+8的字資料讀入寄存器R0。
LDR R0,[R1,R2] ! ;将存儲器位址為R1+R2的字資料讀入寄存器R0,并将新位址R1+R2寫入R1。
LDR R0,[R1,#8] ! ;将存儲器位址為R1+8的字資料讀入寄存器R0,并将新位址R1+8寫入R1。
LDR R0,[R1],R2 ;将存儲器位址為R1的字資料讀入寄存器R0,并将新位址R1+R2寫入R1。
LDR R0,[R1,R2,LSL#2]! ;将存儲器位址為R1+R2×4的字資料讀入寄存器R0,并将新位址R1+R2×4寫入R1。
LDR R0,[R1],R2,LSL#2 ;将存儲器位址為R1的字資料讀入寄存器R0,并将新位址R1+R2×4寫入R1。
2、LDRB指令
LDRB指令的格式為:
LDR{條件}B 目的寄存器,<存儲器位址>
LDRB指令用于從存儲器中将一個8位的位元組資料傳送到目的寄存器中,同時将寄存器的高24位清零。該指令通常用于從存儲器中讀取8位的位元組資料到通用寄存器,然後對資料進行處理。當程式計數器PC作為目的寄存器時,指令從存儲器中讀取的字資料被當作目的位址,進而可以實作程式流程的跳轉。
指令示例:
LDRB R0,[R1] ;将存儲器位址為R1的位元組資料讀入寄存器R0,并将R0的高24位清零。
LDRB R0,[R1,#8] ;将存儲器位址為R1+8的位元組資料讀入寄存器R0,并将R0的高24位清零。
3、LDRH指令
LDRH指令的格式為:
LDR{條件}H 目的寄存器,<存儲器位址>
LDRH指令用于從存儲器中将一個16位的半字資料傳送到目的寄存器中,同時将寄存器的高16位清零。該指令通常用于從存儲器中讀取16位的半字資料到通用寄存器,然後對資料進行處理。當程式計數器PC作為目的寄存器時,指令從存儲器中讀取的字資料被當作目的位址,進而可以實作程式流程的跳轉。
指令示例:
LDRH R0,[R1] ;将存儲器位址為R1的半字資料讀入寄存器R0,并将R0的高16位清零。
LDRH R0,[R1,#8] ;将存儲器位址為R1+8的半字資料讀入寄存器R0,并将R0的高16位清零。
LDRH R0,[R1,R2] ;将存儲器位址為R1+R2的半字資料讀入寄存器R0,并将R0的高16位清零。
4、STR指令
STR指令的格式為:
STR{條件} 源寄存器,<存儲器位址>
STR指令用于從源寄存器中将一個32位的字資料傳送到存儲器中。該指令在程式設計中比較常用,且尋址方式靈活多樣,使用方式可參考指令LDR。
指令示例:
STR R0,[R1],#8 ;将R0中的字資料寫入以R1為位址的存儲器中,并将新位址R1+8寫入R1。
STR R0,[R1,#8] ;将R0中的字資料寫入以R1+8為位址的存儲器中。
5、STRB指令
STRB指令的格式為:
STR{條件}B 源寄存器,<存儲器位址>
STRB指令用于從源寄存器中将一個8位的位元組資料傳送到存儲器中。該位元組資料為源寄存器中的低8位。
指令示例:
STRB R0,[R1] ;将寄存器R0中的位元組資料寫入以R1為位址的存儲器中。
STRB R0,[R1,#8] ;将寄存器R0中的位元組資料寫入以R1+8為位址的存儲器中。
6、STRH指令
STRH指令的格式為:
STR{條件}H 源寄存器,<存儲器位址>
STRH指令用于從源寄存器中将一個16位的半字資料傳送到存儲器中。該半字資料為源寄存器中的低16位。
指令示例:
STRH R0,[R1] ;将寄存器R0中的半字資料寫入以R1為位址的存儲器中。
STRH R0,[R1,#8] ;将寄存器R0中的半字資料寫入以R1+8為位址的存儲器中。
3.3.6 批量資料加載/存儲指令
ARM微處理器所支援批量資料加載/存儲指令可以一次在一片連續的存儲器單元和多個寄存器之間傳送資料,批量加載指令用于将一片連續的存儲器中的資料傳送到多個寄存器,批量資料存儲指令則完成相反的操作。常用的加載存儲指令如下:
— LDM 批量資料加載指令
— STM 批量資料存儲指令
LDM(或STM)指令
LDM(或STM)指令的格式為:
LDM(或STM){條件}{類型} 基址寄存器{!},寄存器清單{ ∧}
LDM(或STM)指令用于從由基址寄存器所訓示的一片連續存儲器到寄存器清單所訓示的多個寄存器之間傳送資料,該指令的常見用途是将多個寄存器的内容入棧或出棧。其中,{類型}為以下幾種情況:
IA 每次傳送後位址加1;
IB 每次傳送前位址加1;
DA 每次傳送後位址減1;
DB 每次傳送前位址減1;
FD 滿遞減堆棧;
ED 空遞減堆棧;
FA 滿遞增堆棧;
EA 空遞增堆棧;
{!}為可選字尾,若選用該字尾,則當資料傳送完畢之後,将最後的位址寫入基址寄存器,否則基址寄存器的内容不改變。
基址寄存器不允許為R15,寄存器清單可以為R0~R15的任意組合。
{ ∧ }為可選字尾,當指令為LDM且寄存器清單中包含 R15, 選用該字尾時表示:除了正常的資料傳送之外,還将SPSR複制到CPSR。同時,該字尾還表示傳入或傳出的是使用者模式下的寄存器,而不是目前模式下的寄存器。
指令示例:
STMFD R13!,{R0,R4-R12,LR} ;将寄存器清單中的寄存器(R0,R4到R12,LR)存入堆棧。
LDMFD R13!,{R0,R4-R12,PC} ;将堆棧内容恢複到寄存器(R0,R4到R12,LR)。
3.3.7 資料交換指令
ARM微處理器所支援資料交換指令能在存儲器和寄存器之間交換資料。資料交換指令有如下兩條:
— SWP 字資料交換指令
— SWPB 位元組資料交換指令
1、SWP指令
SWP指令的格式為:
SWP{條件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用于将源寄存器 2所指向的存儲器中的字資料傳送到目的寄存器中,同時将源寄存器 1中的字資料傳送到源寄存器 2所指向的存儲器中。顯然,當源寄存器 1和目的寄存器為同一個寄存器時,指令交換該寄存器和存儲器的内容。
指令示例:
SWP R0,R1,[R2] ;将R2所指向的存儲器中的字資料傳送到R0,同時将R1中的字數