ARM指令集詳解2
ARM微處理器支持加載/存儲(chǔ)指令用于在寄存器和存儲(chǔ)器之間傳送數(shù)據(jù),加載指令用于將存儲(chǔ)器中的數(shù)據(jù)傳送到寄存器,存儲(chǔ)指令則完成相反的操作。
本文引用地址:http://m.butianyuan.cn/article/201611/318756.htmLDR{條件} 目的寄存器, <存儲(chǔ)器地址>
指令用于將存儲(chǔ)器中的一個(gè)32位的字?jǐn)?shù)據(jù)傳送到目的寄存器中。本指令通常用于將存儲(chǔ)器上的字?jǐn)?shù)據(jù)傳送到通用寄存器。
LDR R0,[R1]
將存儲(chǔ)器地址為R1的字?jǐn)?shù)據(jù)讀入寄存器R0
LDR R0,[R1,R2]
將存儲(chǔ)器地址為R1+R2的字?jǐn)?shù)據(jù)讀入寄存器R0。
LDR R0,[R1,#8]
將存儲(chǔ)器地址為R1+8的字?jǐn)?shù)據(jù)讀入寄存器R0
LDR R0, [R1,R2]!
將存儲(chǔ)器地址R1+R2的字?jǐn)?shù)據(jù)讀入寄存器R0,同時(shí)將新地址R1+R2寫入R1。
LDR R0, [R1,#5]!
將存儲(chǔ)器地址R1+5的字?jǐn)?shù)據(jù)讀入寄存器R0,同時(shí)將新地址R1+5寫入到R1。
LDR R0,[R1], R2
將存儲(chǔ)器地址為R1的字?jǐn)?shù)據(jù)讀入寄存器R0,并將新地址R1+R2寫入R1。
LDR R0,[R1,R2,LSL #2]!
將存儲(chǔ)器地址為R1+R2*4的字?jǐn)?shù)據(jù)讀入到寄存器R0中,并將新地址R1+R2*4寫入R1
LDR R0, [R1], R2, LSL #2
將存儲(chǔ)器地址為R1的字?jǐn)?shù)據(jù)讀入寄存器R0,并進(jìn)新地址R1+R2*4寫入R1。
LDR{條件}B 目的寄存器,<存儲(chǔ)器地址>
LDRB指令用于從存儲(chǔ)器中將一個(gè)8位的字節(jié)數(shù)據(jù)傳送到目的寄存器中,同時(shí)將寄存器的高24位清零。
LDRB R0,[R1]
LDRB R0,[R1,#8]
LDR{條件}H 目的寄存器,<存儲(chǔ)器地址>
LDRH指令用于從存儲(chǔ)器中將一個(gè)16位的半字?jǐn)?shù)據(jù)傳送到目的寄存器中,同時(shí)將寄存器的高16位清零。
LDRH R0,[R1]
LDRH R0,[R1,R2]
STR{條件} 源寄存器,<存儲(chǔ)器地址>
STR指令用于從源寄存器中將一個(gè)32位字?jǐn)?shù)據(jù)傳送到存儲(chǔ)器中。
STR R0,[R1], #8
STR R0,[R1,#8]
ARM微處理器所支持的批量數(shù)據(jù)加載/存儲(chǔ)指令可以一次在一片連續(xù)的存儲(chǔ)器單元和多個(gè)寄存器之間傳遞數(shù)據(jù),批量加載指令用于將一片連續(xù)的存儲(chǔ)單元的數(shù)據(jù)傳送到多個(gè)寄存器,批量數(shù)據(jù)存儲(chǔ)指令則完成相反的操作。
LDM
STM
LDM{條件}{類型}
指令用于從由基址寄存器所指示的一片連續(xù)存儲(chǔ)器到寄存器列表所指示的多個(gè)寄存器之間傳送數(shù)據(jù),該指令的常見用途是將多個(gè)寄存器的內(nèi)容入?;虺鰲!F渲?,{類型}為以下幾種情況:
IA 每次傳送后地址加1;
IB 每次傳送前地址加1;
DA 每次傳送后地址減1;
DB 每次傳送前地址減1;
FD 滿遞減堆棧;
ED 空遞減堆棧;
FA 滿遞增堆棧;
EA 空遞增堆棧;
{!}為可選后綴,若選用該后綴,則當(dāng)數(shù)據(jù)傳送完畢之后,將最后的地址寫入基址寄存器,否則基址寄存器的內(nèi)容部改變?;芳拇嫫鞑辉试S為R15,寄存器列表可以為R0-R15的任意組合。
{^}為可選后綴,當(dāng)指令為LDM且寄存器列表中包含R15,選用該后綴時(shí)表示:除了正常的數(shù)據(jù)傳送之外,還將SPSR到CPSR。
STMFD R13!, {R0,R4-R12,LR}
將寄存器列表中的寄存器(R0,R4到R12,LR)存入堆棧。
LDMFD R13!, {R0,R4-R12,LR}
將堆棧內(nèi)容恢復(fù)到寄存器(R0,R4到R12,LR)。
數(shù)據(jù)交換指令
ARM微處理器所支持?jǐn)?shù)據(jù)交換指令能在存儲(chǔ)器和寄存器之間交換數(shù)據(jù)。
SWP 字?jǐn)?shù)據(jù)交換指令
SWPB 字節(jié)數(shù)據(jù)交換指令
SWP{條件} 目的寄存器, 源寄存器1,[源寄存器2]
SWP指令用于將源寄存器2所指向的存儲(chǔ)器中的字?jǐn)?shù)據(jù)傳送到目的寄存器中,同時(shí)將源寄存器1中的字?jǐn)?shù)據(jù)傳送到源寄存器2所指向的存儲(chǔ)器中,顯然,當(dāng)源寄存器1和目的寄存器為同一個(gè)寄存器時(shí),指令交換該寄存器和存儲(chǔ)器的內(nèi)容。
SWP R0,R1,[R2]
SWP R0,R0,[R1]
移位指令
ARM微處理器支持?jǐn)?shù)據(jù)的移位操作,移位操作在ARM指令集中不作為單獨(dú)的指令使用,它只能作為指令格式中是一個(gè)字段。
LSL logical shifter left
ASL arithmetic shifter left
LSR logical shifter right
ASR arithmetic shifter right
ROR rotate right
通用寄存器,LSL操作數(shù)
LSL可完成對(duì)寄存器中的內(nèi)容進(jìn)行邏輯左移操作,按操作數(shù)所指定的數(shù)量向左移位,低位用零來填充。其中,操作數(shù)可以是通用寄存器,也可以是立即數(shù)(0—31)。
MOV R0,R1,LSL#2
將R1中的內(nèi)容左移兩位后傳送到R0中。
通用寄存器,ROR 操作數(shù)
ROR可完成對(duì)通用寄存器中的內(nèi)容進(jìn)行循環(huán)右移的操作,按操作數(shù)所指定的數(shù)量向右循環(huán)移位,左端用右端移出的位來填充。其中,操作數(shù)可以是通用寄存器,也可以是立即數(shù)(0-31)。顯然,當(dāng)進(jìn)行32位的循環(huán)右移操作時(shí),通用寄存器中的值不改變。
MOV R0,R1,ROR#2
將R1中的內(nèi)容循環(huán)右移兩位后傳送到R0中。
異常產(chǎn)生的指令
ARM微處理器所支持的異常指令如下兩條:
SWI 軟件中斷指令
BKPT 斷點(diǎn)中斷指令
SWI{條件} 24位的立即數(shù)
SWI指令用于產(chǎn)生軟件中斷,以便用戶程序能調(diào)用操作系統(tǒng)的系統(tǒng)API。操作系統(tǒng)在SWI的異常處理程序中提供了相應(yīng)的系統(tǒng)服務(wù),指令中24位的立即數(shù)指定用戶程序調(diào)用的API類型。
SWI 0x02
該指令調(diào)用操作系統(tǒng)編號(hào)為02的系統(tǒng)例程。
偽指令
這些助記符與指令系統(tǒng)的助記符不同,沒有相對(duì)應(yīng)的操作碼,通常稱這些特殊指令助記符為偽指令,他們所完成的操作稱為偽操作。偽指令在源程序中的作用是為完成匯編程序作各種準(zhǔn)備工作,這些偽指令僅在匯編過程中起作用,一旦匯編結(jié)束,偽指令的使命就完成。
ARM中有如下幾種偽指令:符號(hào)定義偽指令、數(shù)據(jù)定義偽指令、匯編控制偽指令、宏指令以及其他偽指令。
符號(hào)定義偽指令用于定義ARM匯編程序中的變量、對(duì)變量賦值以及定義寄存器的別名等操作。常見的符號(hào)定義偽指令有如下幾種:
定義全局變量的GBLA、GBLL和GBLS
定義局部變量的LCLA、LCLL和LCLS
對(duì)變量賦值的SETA、SETL、SETS
為通用寄存器列表定義名稱的RLIST
GBLA:定義一個(gè)全局的數(shù)字變量,并初始化為0;
GBLL:定義一個(gè)全局的邏輯變量,并初始化為F(假);
GBLS:定義一個(gè)全局的字符串變量,并初始化為空;
以上三條偽指令用于定義全局變量,因此在整個(gè)程序范圍內(nèi)變量名必須唯一。
GBLA Test1
定義一個(gè)全局的數(shù)字變量,變量名為Test1
Test1 SETA 0xaa
進(jìn)該變量賦值為0xaa
GBLL Test2
定義一個(gè)全局的邏輯變量,變量名為Test2
Test2 SETL {TRUE}
將該變量賦值為真
GBLS Test3
定義一個(gè)全局的字符串變量,變量名為Test3
Test3 SETS “testing”
將該變量賦值為“testing”
名稱 RLIST {寄存器列表}
RLIST 偽指令用于對(duì)一個(gè)通用寄存器列表定義名稱,使用該偽指令定義的列表名稱可在ARM指令LDM/STM中使用。在LDM/STM指令中,列表中的寄存器訪問次序?yàn)楦鶕?jù)寄存器的編號(hào)由低到高,而與列表中的寄存器排序無關(guān)。
Reglist RLIST {R0-R5,R8,R10}
數(shù)據(jù)定義偽指令一般用于為特定的數(shù)據(jù)分配存儲(chǔ)單元,同時(shí)可完成已分配存儲(chǔ)單元的初始化。
DCB DCW DCD DCFD DCFS DCQ SPACE MAP FIELD
標(biāo)號(hào) DCB 表達(dá)式
DCB偽指令用于分配一片連續(xù)的字節(jié)存儲(chǔ)單元并用偽指令中指定的表達(dá)式初始化。其中,表達(dá)式可以為0-255的數(shù)字或字符串。DCB也可用“=”代替。
Str DCB “This is a test!”
標(biāo)號(hào) SPACE 表達(dá)式
SPACE偽指令用于分配一片連續(xù)的存儲(chǔ)區(qū)域并初始化為0.其中,表達(dá)式為要分配的字節(jié)數(shù)。SPACE也可用“%”代替。
DateSpace SPACE 100
MAP 表達(dá)式 {基址寄存器}
MAP偽指令用于定義一個(gè)結(jié)構(gòu)化的內(nèi)存表的首地址。MAP也可用“^”代替。表達(dá)式可以為程序中的標(biāo)號(hào)或數(shù)學(xué)表達(dá)式,基址寄存器為可選項(xiàng),當(dāng)基址寄存器選項(xiàng)不存在時(shí),表達(dá)式的值即為內(nèi)存表的首地址,當(dāng)該選項(xiàng)存在時(shí),內(nèi)存表的首地址為表達(dá)式的值與基址寄存器的和。MAP偽指令通常與FIELD偽指令配合使用來定義結(jié)構(gòu)化的內(nèi)存表。
MAP 0x100,R0
定義結(jié)構(gòu)化內(nèi)存表首地址的值為0x100+R0。
標(biāo)號(hào) FIELD 表達(dá)式
FIELD偽指令用于定義一個(gè)結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域。FILED也可用“#”代替。表達(dá)式的值為當(dāng)前數(shù)據(jù)域在內(nèi)存表中所占的字節(jié)數(shù)。FIELD偽指令常與MAP偽指令配合使用來定義結(jié)構(gòu)化的內(nèi)存表。MAP偽指令定義內(nèi)存表的首地址,F(xiàn)IELD偽指令定義內(nèi)存表中的各個(gè)數(shù)據(jù)域,并可以為每個(gè)數(shù)據(jù)域指定一個(gè)標(biāo)號(hào)供其他的指令引用。
MAP 0x100
A
B
S
匯編控制偽指令:
IF ELSE ENDIF
WHILE WEND
MACRO MEND
MEXIT
WHILE 邏輯表達(dá)式
指令序列
WEND
其他偽指令:
AREA 段名 屬性1,屬性2,......
AREA偽指令用于定義一個(gè)代碼段或數(shù)據(jù)段。其中,段名若以數(shù)字開頭,則該段名需用“|”括起來,如|1_test|。屬性字段表示該代碼段的相關(guān)屬性,多個(gè)屬性用逗號(hào)分隔。常用屬性如下:
CODE:用于定義代碼段,默認(rèn)為READONLY。
DATA:用于定義數(shù)據(jù)段,默認(rèn)為READWRITE。
READONLY:定義本段為只讀,代碼段默認(rèn)為READONLY。
READWRITE;指定本段為可讀可寫,數(shù)據(jù)段的默認(rèn)屬性READWRITE。
ALIGN屬性,使用方式為:
ALIGN 表達(dá)式
在默認(rèn)時(shí),ELF的代碼段和數(shù)據(jù)段是按字對(duì)齊的。
一個(gè)匯編語言程序至少要包含一個(gè)段,當(dāng)程序太長時(shí),也可以將程序分為多個(gè)代碼段和數(shù)據(jù)段。
AREA Init,CODE,READONLY
該偽指令定義了一個(gè)代碼段,段名為Init,屬性為只讀。
ALIGN {表達(dá)式{偏移量}}
ALIGN偽指令可通過添加填充字節(jié)的方式,使當(dāng)前位置滿足一定的對(duì)齊方式。其中,表達(dá)式的值用于指定對(duì)齊方式,可能的取值為2的冪,如1,2,4,8,16等。若未指定表達(dá)式,則將當(dāng)前位置對(duì)齊到下一個(gè)字的位置。偏移量也為一個(gè)數(shù)字表達(dá)式,若使用該字段,則當(dāng)前位置的對(duì)齊方式為:2的表達(dá)式次冪+偏移量。
AREA Init,CODE,READONLY,ALIGN=3
指定后面的指令為8字節(jié)對(duì)齊。
CODE16(或CODE32)
CODE16偽指令通知編譯器,其后的指令序列為16位的Thumb指令。CODE32偽指令通知編譯器,其后的指令序列為32位的ARM指令。因此,在使用ARM指令和Thumb指令混合編程的代碼里,可用這兩條偽指令進(jìn)行切換,但注意他們只通知編譯器其后指令的類型,并不能對(duì)處理器進(jìn)行狀態(tài)的切換。
ENTRY
ENTRY偽指令用于指定匯編程序的入口點(diǎn),在一個(gè)完整的匯編程序中至少要有一個(gè)ENTRY(也可有多個(gè),當(dāng)有多個(gè)ENTRY時(shí),程序的真正入口點(diǎn)由鏈接器指定),但在一個(gè)源文件里最多只能有一個(gè)ENTRY。
名稱 EQU 表達(dá)式{類型}
EQU偽指令用于為程序中的常量、標(biāo)號(hào)等定義一個(gè)等效的字符名稱,類似于C語言中的#define。其中EQU可用“*”代替。
Test EQU 50
Addr EQU 0x55,CODE32
EXPORT 標(biāo)號(hào)
EXPORT偽指令用于在程序中聲明一個(gè)全局的標(biāo)號(hào),該標(biāo)號(hào)可在其他的文件中引用。EXPORT可用GLOBAL代替。標(biāo)號(hào)在程序中區(qū)分大小寫。
AREA Init,CODE,READONLY
EXPORT Stest
聲明一個(gè)可全局引用的標(biāo)號(hào)Stest
IMPORT 標(biāo)號(hào)
IMPORT偽指令用于通知編譯器要使用的標(biāo)號(hào)在其他的源文件中定義,但要在當(dāng)前源文件中引用。標(biāo)號(hào)在程序中區(qū)分大小寫。
AREA Init,CODE,READONLY
IMPORT Main
通知編譯器當(dāng)前文件要引用標(biāo)號(hào)Main,但Main在其他源文件中定義
END
END偽指令用于通知編譯器已經(jīng)到了源程序的結(jié)尾。
評(píng)論