arm匯編指令是學習匯編必須要掌握的,很多人覺得arm匯編指令記得很頭疼,而且還很亂,在這里一個美女學霸總結出了最全面的arm匯編指令,看看學霸是怎么總結的,還在等什么,快收藏起來。
剛開始就是ARM匯編語言基本結構,這是必須先要了解的:
AREA Init, CODE, READONLY
ENTRY
Start
LDR R0, =0x3FF5000
LDR R1, 0xFF
STR R1, [R0]
LDR R0, =0x3FF5008
LDR R1, 0x01
STR R1, [R0]
... ... ... ... ... ...
END
指令格式
ARM指令的基本格式:
opcode:指令助記碼,如:MOV
con:執行條件,如NE,EQ
S:是否影響CPSR寄存器的值,設置時影響CPSR
Rd:目標寄存器
Rn:第一個操作數的寄存器
operand2:第二個操作數
ARM處理器尋址方式
尋址方式是根據指令中給出的地址碼字段來實現尋找真實操作數地址的方式。ARM處理器有九種尋址方式,寄存器尋址、立即數尋址、寄存器偏移尋址為數據處理指令操作數尋址方式,寄存器間接尋址、基址尋址、多寄存器尋址、堆棧尋址、相對尋址為存儲器訪問指令操作數尋址方式。
a、寄存器尋址
操作數的值存在寄存器中,指令中的地址碼字段指出的是寄存器編號,指令執行時直接取出寄存器值操作。例如:
MOV R0,R1
SUB R0,R1,R2
b、立即尋址
立即尋址指令中的操作碼字段部分后面的地址碼部分就是操作數本身,即數據包含在指令當中。例如:
MOV R0,#0xff
立即數要以“#”為前綴,十六進制以“0x”表示
c、寄存器偏移尋址
寄存器偏移尋址是ARM指令集特有的尋址方式,當第2操作數是寄存器,在執行操作之前,可以做一次移位操作。
MOV R0,R2,LSL #3
ANDS R1,R1,R2,LSL R3
d、寄存器間接尋址
寄存器間接尋址指令中的地址碼給出的是一個通用寄存器的編號,所需的操作數保存在寄存器指定地址的存儲單元中,即寄存器為操作數的地址指針。
LDR R1,[R2] ;將R2指向的單元中的數據保存再R1中
SWP R1,R1,[R2] ;將寄存器R1的值和R2指向的單元中進行內容交換
e、基址尋址
基址尋址就是將基址寄存器的內容與指令中給出的偏移量進行相加,形成操作數的有效地址。基址尋址用于訪問基址附近的存儲單元,常用于查表、數組操作以及功能不見寄存器訪問等。
LDR R2,[R3,#0x0c] ;讀取R3 0x0c地址指向的存儲單元的內容,放入R2
STR R1,[R0,#-4]! ;先R0=R0-4,然后把R1的值寄存到R0所指向的單元中
LDR R1,[R0,R3,LSL #1] ;將R0 R3*2地址上的單元的內容讀出,并存入R1中
f、多寄存器尋址
多寄存器尋址即一次可傳送幾個寄存器的值,允許一條指令傳送16個寄存器的任何子集或所有的存儲器。
LDMIA R1!,{R2-R7,R12};將R1指向的單元中的數據讀出到R2---R7、R12中(R1自自動 )
STMIA R0!,{R2-R7,R12};將R2---R7、R12中的數據一次讀入到R0指向的單元中(R0自動 )
g、堆棧尋址
堆棧是一種按特定順序進行存取的存儲區,操作順序分為“先進后出”和“后進先出”,堆棧尋址是隱含的,它使用一個專門的寄存器(堆棧指針)指向的存儲區域(堆棧),指針所指向的存儲單元即是堆棧的棧頂。
STMFD SP!,{R1-R7,LR} ;將R1---R7、LR入棧。滿遞減堆棧
LDMFD SP!,{R1-R7,LR} ;數據出棧,放入R1---R7、LR寄存器,滿遞減堆棧
h、塊拷貝尋址
多寄存器傳送指令用于將一塊數據從存儲器的某一位置拷貝到另一位置。
STMIA R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中。
;存儲指針在保存第一個值之后增加,
;增長方向為向上增長。
STMIB R0!,{R1-R7} ;將R1~R7的數據保存到存儲器中。
;存儲指針在保存第一個值之前增加,
;增長方向為向上增長。
i、相對尋址
相對尋址是基址尋址的一種變通。由程序計數器PC提供基址地址,指令中的地址碼字段為偏移量。兩者相加后得到的地址即為操作數的有效地址。
ARM存儲器訪問指令
ARM處理器是加載/存儲體系結構的典型RISC處理器,對存儲器的訪問只能用加載和存儲指令實現。ARM的加載/存儲指令可以實現字、半字、字節操作。
1、LDR和STR
加載/存儲字和無符號字節指令。使用單一數據傳送指令來裝載和存儲單一字節或字的數據。LDR指令用于從內存中讀取數據放入內存中,STR指令用于將寄存器中的數據保存到內存中。
指令格式如下:
LDR[cond][T] Rd,<地址>;
加載指定地址上的數據(字),放入Rd中
STR[cond][T] Rd,<地址>;
存儲數據(字)到指定地址的存儲單元,要存儲的數據在Rd中
LDR[cond]B[T] Rd,<地址>;加載字節數據,放入Rd中,Rd低字節有效
STR[cond]B[T] Rd,<地址>;存儲字節數據,要存儲的數據在Rd中
指令T表示在處理器特權模式下,存儲系統也將訪問看做是在用戶模式下。
STR R0,[R1],#8;將R0中內容寫入R1為地址的內存中,并將新地址R1+8寫入R1。
STR R0,[R1,#8];將R0中的字數據寫入以R1+8為地址的存儲器中。
LDR/STR指令尋址非常靈活,由兩部分組成,一部分為基址寄存器,可以是任一通用寄存器,另一部分為地址偏移量,由以下三種格式:
a、立即數
立即數可以是一個無符號數值,這個數值可以加到基址寄存器或由基址寄存器減去,例如:
LDR R0,[R1,#0x12];將R1+0x12地址處的數據讀出保存到R0寄存器中
LDR R0,[R1,#-0x12];將R1-0x12地址處的數據讀出保存到R0寄存器中
LDR R0,[R1];將R1地址處的數據讀出保存到R0寄存器中
b、寄存器
寄存器中的數值可以加到基址寄存器,也可以從基址寄存器中減去這個值,例如:
LDR R0,[R1,R2];將R1+R2地址處的數據讀出,保存到R0寄存器中
LDR R0,[R1,-R2];將R1-R2地址處的數據讀出,保存到R0寄存器中
c、寄存器及移位常數
基址寄存器加上或減去寄存器移位后的值
LDR R0,[R1,R2,LSL#2];將R1+R2*4地址處的數據讀出,保存到寄存器R0
LDR R0,[R1,-R2,LSL#2];將R1-R2*4地址處的數據讀出,保存到寄存器R0
LDRB指令用于從存儲器中將一個8位的字節數據傳送到目的寄存器中,同時將寄存器的高24位清零。 該指令通常用于從存儲器中讀取8位的字節數據到通用寄存器,然后對數據進行處理。當程序計數器PC作為目的寄存器時,指令從存儲器中讀取的字數據被當作目 的地址,從而可以實現程序流程的跳轉。
LDRH指令的格式為:
LDR{條件}H 目的寄存器,<存儲器地址>
LDRH指令用于從存儲器中將一個16位的半字數據傳送到目的寄存器中,同時將寄存器的高16位清零。 該指令通常用于從存儲器中讀取16位的半字數據到通用寄存器,然后對數據進行處理。當程序計數器PC作為目的寄存器時,指令從存儲器中讀取的字數據被當作 目的地址,從而可以實現程序流程的跳轉。
STRB指令的格式為:
STR{條件}B 源寄存器,<存儲器地址>
STRB指令用于從源寄存器中將一個8位的字節數據傳送到存儲器中。該字節數據為源寄存器中的低8位。
STRH指令的格式為:
STR{條件}H 源寄存器,<存儲器地址>
STRH指令用于從源寄存器中將一個16位的半字數據傳送到存儲器中。該半字數據為源寄存器中的低16位。
應用示例:
GPIO設置:
GPIO_BASE EQU 0xE0028000;定義GPIO寄存器的基地址
LDR R0,=GPIO_BASE
LDR R1,=0x00FFFFFF00
STR R1,[R0,#0x0C];將0xE002800C地址的值設為0x00FFFFFF00
MOV R1,0x00F00000
STR R1,[R0,#0x04];將0xE0028004地址的值設為0x00F00000
2、LDM和STM
批量加載/存儲指令可以實現在一組寄存器和一塊連續的內存單元之間傳輸數據,指令格式如下:
LDM[cond]<模式> Rn[!],reglist{^}
STM[cond]<模式> Rn[!],reglist{^}
模式有八種:
IA 每次傳送后地址加4;
IB 每次傳送前地址加4;
DA 每次傳送后地址減4;
DB 每次傳送前地址減4;
FD 滿遞減堆棧;
ED 空遞減堆棧;
FA 滿遞增堆棧;
EA 空遞增堆棧;
3、SWP
寄存器和存儲器交換指令,指令格式:
SWP[cond][B] Rd,Rm,[Rn]
將Rn的值為地址的內存單元的值讀取到Rd寄存器中,同時將寄存器Rm的值寫入該內存單元。
如果有B,則交換字節,否則交換32位字;
ARM數據處理指令
數據處理指令分為數據傳送指令、算數邏輯運算指令、比較指令
數據處理指令只能對寄存器的內容進行操作
1、數據傳送指令
A、MOV
指令格式:
MOV[con][S] Rd,operand2
MOV R0,#0x04
MOV R0,R1
MOVS R3,R2,LSL#2
MOV PC,LR;PC=LR,子程序返回
B、MVN
指令格式:
MOV[con][S] Rd,operand2
MVN R0,R1
MVN R2,#0xFF;R2位0xFFFFFF00
2、算數邏輯運算指令
A、ADD加法運算指令
指令格式:
ADD[con][S] Rd,Rn,operand2
將operand2數據與Rn的值相加,結果保存到Rd寄存器
ADD指令用于把兩個操作數相加,并將結果存放到目的寄存器中。操作數1應是一個寄存器,操作數2可以是一個寄存器,被移位的寄存器,或一個立即數。
ADD R0,R1,R2
ADD R0,R1,#0x12
ADDS R0,R1,R2,LSL#2
B、SUB減法運算指令
SUB[con][S] Rd,Rn,operand2
用寄存器Rn的值減去operand2,結果保存在Rd中,指令格式:
SUBS R0,R0,#1
SUBS R0,R1,R2
RBS逆向減法指令
用寄存器operand2減去Rn,結果保存到Rd中,指令格式:
RBS[con][S] Rd,Rn,operand2
RSB R0,R1,#0x100;R0=0x100-R1
C、ADC帶進位加法指令
將operand2的數據與Rn的值相加,再加上CPSR中的C條件標志位,結果保存到Rd寄存器,指令格式:
ADC[con][S] Rd,Rn,operand2
D、AND邏輯與操作指令
將寄存器operand2的值與寄存器Rn的值按位作邏輯與操作,結果保存到Rd中,指令格式:
AND[con][S] Rd,Rn,operand2
ANDS R0,R1,#0x01
AND R0,R1,R2
E、ORR邏輯或操作指令
將寄存器operand2的值與寄存器Rn的值按位作邏輯或操作,結果保存到Rd中,指令格式:
ORR[con][S] Rd,Rn,operand2
ORR R0,R0,#0x0F;將R0的低4位置1
F、EOR邏輯異或操作指令
將寄存器operand2的值與寄存器Rn的值按位作邏輯異或操作,結果保存到Rd中,指令格式:
ERR[con][S] Rd,Rn,operand2
H、BIC位清零操作指令
將寄存器Rn的值與寄存器operand2的值反碼按位作邏輯與操作,結果保存到Rd中,指令格式:
BIC[con][S] Rd,Rn,operand2
BIC R1,R1,#0x0F
3、比較指令
A、CMP比較指令
用寄存器Rn的值減去寄存器operand2的值,根據操作的結果更新CPSR中相應的條件標志位,以便后面的指令根據相應的條件標志位判斷是否執行,指令格式:
CMP[con] Rn,operand2
B、CMN負數比較指令
CMN[con] Rn,operand2
CMN指令用于把一個寄存器的內容和另一個寄存器的內容或立即數取反后進行比較,同時更新CPSR中條件標志位的值。該指令實際完成操作數1和操作數2相 加,并根據結果更改條件標志位。
指令示例:
CMN R1,R0 ;將寄存器R1的值與寄存器R0的值相加,并根據 結果設置CPSR的標志位
4、乘法指令
A、MUL 32位乘法指令
將Rm與Rs中的值相乘,結果的低32位保存到Rd中,指令格式:
MUL[con][S] Rd,Rm,Rs
MUL R0,R1,R2
B、MLA 32位乘法疊加指令
將Rm與Rs中的值相乘,結果再與Rn相加,低32位保存到Rd中,指令格式:
MLA[con][S] Rd,Rm,Rs,Rn
MLA R0,R1,R2,R3
C、UMULL 64位無符號乘法指令
將Rm與Rs的值作無符號數相乘,結果的低32位保存到RdLo中,高32位保存到RdHi中,指令格式:
UMULL[con][S] RdLo,RdHi,Rm,Rs
UMULL R0,R1,R4,R5;(R1,R0)=R4*R5
D、SMULL 64位有符號乘法指令
將Rm與Rs的值作有符號數相乘,結果的低32位保存到RdLo中,高32位保存到RdHi中,指令格式:
SMULL[con][S] RdLo,RdHi,Rm,Rs
SMULL R0,R1,R4,R5;(R1,R0)=R4*R5
ARM跳轉指令
1、B跳轉指令
跳轉到指定的地址執行程序,指令格式:
B[con] label
B hello
B #0x30008000
2、BL帶鏈接的跳轉指令
將下一條指令的地址拷貝到R14(LR)鏈接寄存器中,然后跳轉到指定地址運行程序,指令格式:
BL[con] label
BL hello
BL用于子函數的調用
3、BX帶狀態切換的跳轉指令
BX指令的格式為:
BX{條件}目標地址
BX指令跳轉到指令中所指定的目標地址,目標地址處的指令既可以是ARM指令,也可以是Thumb指令。
數據交換指令
1、SWP指令
SWP指令的格式為:
SWP{條件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用于將源寄存器2所指向的存儲器中的字數據傳送到目的寄存器中,同時將源寄存器1中的字數據傳送到源寄存器2所指向的存儲器中。顯然,當源寄存 器1和目的寄存器為同一個寄存器時,指令交換該寄存器和存儲器的內容。
指令示例:
SWP R0,R1,[R2] ;將R2所指向的存儲器中的字數據傳送到R0,同時將R1 中的字數據傳送到R2所指向的存儲單元。
SWP R0,R0,[R1] ;該指令完成將R1所指向的存儲器中的字數 據與R0中的數據交換。
2、SWPB指令
SWPB指令的格式為:
SWP{條件}B 目的寄存器,源寄存器1,[源寄存器2]
SWPB指令用于將源寄存器2所指向的存儲器中的字節數據傳送到目的寄存器中,目的寄存器的高24清零,同時將源寄存 器1中的字節數據傳送到源寄存器2所指向的存儲器中。顯然,當源寄存器1和目的寄存器為同一個寄存器時,指令交換該寄存器和存儲器的內容。
指令示例:
SWPB R0,R1,[R2] ;將R2所指向的存儲器中的字節數據傳送到 R0,R0的高24位清零,同時將R1中的低8位數據傳送到R2所指向的存儲單元。
SWPB R0,R0,[R1] ;該指令完成將R1所指向的存儲器中的 字節數據與R0中的低8位數據交換。
程序狀態寄存器訪問指令
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中的控制位域
ARM協處理器指令
1、CDP指令
CDP指令的格式為:
CDP{條件} 協處理器編碼,協處理器操作碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操作碼2。
CDP指令用于ARM處理器通知ARM協處理器執行特定的操作,若協處理器不能成功完成特定的操作,則產生未定義指令異常。其中協處理器操作碼1和協處理 器操作碼2為協處理器將要執行的操作,目的寄存器和源寄存器均為協處理器的寄存器,指令不涉及ARM處理器的寄存器和存儲器。
指令示例:
CDP P3,2,C12,C10,C3,4 ;該指令完成協處理器P3的初始化
2、LDC指令
LDC指令的格式為:
LDC{條件}{L} 協處理器編碼,目的寄存器,[源寄存器]
LDC指令用于將源寄存器所指向的存儲器中的字數據傳送到目的寄存器中,若協處理器不能成功完成傳送操作,則產生未定義指令異常。其中,{L}選項表示指 令為長讀取操作,如用于雙精度數據的傳輸。
指令示例:
LDC P3,C4,[R0] ;將ARM處理器的寄存器R0所指向的存儲器中的字數 據傳送到協處理器P3的寄存器C4中。
3、STC指令
STC指令的格式為:
STC{條件}{L} 協處理器編碼,源寄存器,[目的寄存器]
STC指令用于將源寄存器中的字數據傳送到目的寄存器所指向的存儲器中,若協處理器不能成功完成傳送操作,則產生未定義指令異常。其中,{L}選項表示指 令為長讀取操作,如用于雙精度數據的傳輸。
指令示例:
STC P3,C4,[R0] ;將協處理器P3的寄存器C4中的字數據傳送到ARM處理 器的寄存器R0所指向的存儲器中。
4、MCR指令
MCR指令的格式為:
MCR{條件} 協處理器編碼,協處理器操作碼1,源寄存器,目的寄存器1,目的寄存器2,協處理器操作碼2。
MCR指令用于將ARM處理器寄存器中的數據傳送到協處理器寄存器中,若協處理器不能成功完成操作,則產生未定義指令異常。其中協處理器操作碼1和協處理 器操作碼2為協處理器將要執行的操作,源寄存器為ARM處理器的寄存器,目的寄存器1和目的寄存器2均為協處理器的寄 存器。
指令示例:
MCR P3,3,R0,C4,C5,6 ;將ARM處理器寄存器R0中的數據傳送到協處 理器P3的寄存器C4和C5中。
5、MRC指令
MRC指令的格式為:
MRC{條件} 協處理器編碼,協處理器操作碼1,目的寄存器,源寄存器1,源寄存器2,協處理器操作碼2。
MRC指令用于將協處理器寄存器中的數據傳送到ARM處理器寄存器中,若協處理器不能成功完成操作,則產生未定義指令異常。其中協處理器操作碼1和協處理 器操作碼2為協處理器將要執行的操作,目的寄存器為ARM處理器的寄存器,源寄存器1和源寄存器2均為協處理器的寄存器。
指令示例:
MRC P3,3,R0,C4,C5,6 ;該指令將協處理器P3的寄存器中的數據傳送到 ARM處理器寄存器中。
ARM偽指令
ARM偽指令不是ARM指令集中的指令,只是為了編程方便編譯器定義了偽指令,使用時可以像其他ARM指令一樣使用,但在編譯時這些偽指令將被等效的ARM指令代替。
1、符號定義偽指令
A、全局變量定義
GBLA(GBLL/GBLS) 全局變量名
GBLA 、GBLL 和GBLS 偽指令用于定義一個ARM 程序中的全局變量,并將其初始化。其中:
GBLA 偽指令用于定義一個全局的數字變量,并初始化為0 ;
GBLL 偽指令用于定義一個全局的邏輯變量,并初始化為F(假);
GBLS 偽指令用于定義一個全局的字符串變量,并初始化為空;
由于以上三條偽指令用于定義全局變量,因此在整個程序范圍內變量名必須唯一。
B、局部變量定義
LCLA (LCLL 或 LCLS )局部變量名
LCLA 、LCLL 和LCLS 偽指令用于定義一個ARM 程序中的局部變量,并將其初始化。其中:
LCLA偽指令用于定義一個局部的數字變量,并初始化為0 ;
LCLL偽指令用于定義一個局部的邏輯變量,并初始化為F(假);
LCLS偽指令用于定義一個局部的字符串變量,并初始化為空;
以上三條偽指令用于聲明局部變量,在其作用范圍內變量名必須唯一。
C、變量的賦值
變量名 SETA (SETL 或 SETS )表達式
偽指令 SETA 、SETL 、SETS 用于給一個已經定義的全局變量或局部變量賦值。
SETA偽指令用于給一個數學變量賦值;
SETL偽指令用于給一個邏輯變量賦值;
SETS偽指令用于給一個字符串變量賦值;
其中,變量名為已經定義過的全局變量或局部變量,表達式為將要賦給變量的值。
D、RLIST
名稱 RLIST { 寄存器列表 }
RLIST偽指令可用于對一個通用寄存器列表定義名稱,使用該偽指令定義的名稱可在ARM 指令 LDM/STM中使用。在LDM/STM指令中,列表中的寄存器訪問次序為根據寄存器的編號由低到高,而與列表中的寄存器排列次序無關。
RegList RLIST {R0-R5,R8,R10} 將寄存器列表名稱定義為 RegList ,可在ARM指令LDM/STM中通過該名稱訪問寄存器列表。
2、數據定義偽指令
數據定義偽指令一般用于為特定的數據分配存儲單元,同時可完成已分配存儲單元的初始化。
常見的數據定義偽指令有如下幾種:
DCB 用于分配一片連續的字節存儲單元并用指定的數據初始化。
DCW(DCWU)用于分配一片連續的半字存儲單元并用指定的數據初始化。
DCD (DCDU)用于分配一片連續的字存儲單元并用指定的數據初始化。
DCFD(DCFDU)用于為雙精度的浮點數分配一片連續的字存儲單元并用指定的數據初始化。
DCFS(DCFSU)用于為單精度的浮點數分配一片連續的字存儲單元并用指定的數據初始化。
DCQ(DCQU)用于分配一片以8字節為單位的連續的存儲單元并用指定的數據初始化。
SPACE 用于分配一片連續的存儲單元。
MAP 用于定義一個結構化的內存表首地址。
FIELD 用于定義一個結構化的內存表的數據域。
A、DCB
語法格式:
標號 DCB 表達式
DCB偽指令用于分配一片連續的字節存儲單元并用偽指令中指定的表達式初始化。其中,表達式可以為0~255的數字或字符串。DCB 也可用“=”代替。
使用示例:
Str DCB “This is a test” ;分配一片連續的字節存儲單元并初始化。
B、DCW(或DCWU)
語法格式:
標號 DCW (或DCWU) 表達式
DCW(或DCWU)偽指令用于分配一片連續的半字存儲單元并用偽指令中指定的表達式初始化。
其中,表達式可以為程序標號或數字表達式。
用DCW分配的字存儲單元是半字對齊的,而用DCWU分配的字存儲單元并不嚴格半字對齊。
使用示例:
DataTest DCW 1 ,2 ,3 ;分配一片連續的半字存儲單元并初始化。
C、DCD(或DCDU)
語法格式:
標號 DCD(或DCDU) 表達式
DCD(或DCDU)偽指令用于分配一片連續的字存儲單元并用偽指令中指定的表達式初始化。其中,表達式可以為程序標號或數字表達式。DCD也可 用"&” 代替。
用DCD分配的字存儲單元是字對齊的,而用DCDU分配的字存儲單元并不嚴格字對齊。
使用示例:
DataTest DCD 4 ,5 ,6 ;分配一片連續的字存儲單元并初始化。
D、DCFD(或DCFDU)
語法格式:
標號 DCFD(或DCFDU) 表達式
DCFD(或DCFDU)偽指令用于為雙精度的浮點數分配一片連續的字存儲單元并用偽指令中指定的表達式初始化。每個雙精度的浮點數占據兩個字單元。用 DCFD分配的字存儲單元是字對齊的,而用DCFDU分配的字存儲單元并不嚴格字對齊。
使用示例: FDataTest DCFD 2E115 ,-5E7 ;分配一片連續的字存儲單元并初始化 為指定的雙精度數。
E、DCFS(或DCFSU)
語法格式:
標號 DCFS(或DCFSU) 表達式
DCFS(或DCFSU)偽指令用于為單精度的浮點數分配一片連續的字存儲單元并用偽指令中指定的表達式初始化。每個單精度的浮點數占據一個字單元。用 DCFS分配的字存儲單元是字對齊的,而用DCFSU分配的字存儲單元并不嚴格字對齊。
使用示例:
FDataTest DCFS 2E5 ,-5E -7 ;分配一片連續的字存儲單元并初始化為 指定的單精度數。
F、DCQ(或DCQU)
語法格式:
標號 DCQ(或DCQU) 表達式
DCQ(或DCQU)偽指令用于分配一片以8個字節(雙字)為單位的連續存儲區域并用偽指令中指定的表達式 初始化。 用DCQ分配的存儲單元是字對齊的,而用DCQU 分配的存儲單元并不嚴格字對齊。
使用示例:
DataTest DCQ 100 ;分配一片連續的存儲單元并初始化為指定的值。
G、SPACE
語法格式:
標號 SPACE 表達式
SPACE偽指令用于分配一片連續的存儲區域并初始化為0 。其中,表達式為要分配的字節數。
SPACE也可用“ % ”代替。
使用示例:
DataSpace SPACE 100 ;分配連續100字節的存儲單元并初始化為0 。
H、MAP
語法格式:
MAP 表達式 { ,基址寄存器 }
MAP偽指令用于定義一個結構化的內存表的首地址。MAP也可用“^” 代替。
表達式可以為程序中的標號或數學表達式,基址寄存器為可選項,當基址寄存器選項不存在時,表達式的值即為內存表的首地址,當該選項存在時,內存表的首地址 為表達式的值與基址寄存器的和。
MAP偽指令通常與FIELD偽指令配合使用來定義結構化的內存表。
使用示例:
MAP 0x100 ,R0 ;定義結構化內存表首地址的值為0x100+R0 。
I、FILED
語法格式:
標號 FIELD 表達式
FIELD偽指令用于定義一個結構化內存表中的數據域。FILED 也可用“#” 代替。
表達式的值為當前數據域在內存表中所占的字節數。
FIELD偽指令常與MAP偽指令配合使用來定義結構化的內存表。MAP偽指令定義內存表的首地址,FIELD偽指令定義內存表中的各個數據域,并可以為 每個數據域指定一個標號供其他的指令引用。
注意MAP和FIELD偽指令僅用于定義數據結構,并不實際分配存儲單元。
使用示例:
MAP 0x100 ; 定義結構化內存表首地址的值為0x100。
A FIELD 16 ; 定義A的長度為16字節,位置為0x100。
B FIELD 32 ; 定義B的長度為32字節,位置為0x110。
S FIELD 256 ;定義S的長度為256字節,位置為0x130。
3、匯編控制偽指令
匯編控制偽指令用于控制匯編程序的執行流程,常用的匯編控制偽指令包括以下幾條:
IF 、ELSE 、ENDIF
WHILE 、WEND
MACRO 、MEND、MEXIT
A、IF、ELSE、ENDIF
語法格式:
IF 邏輯表達式
指令序列 1
ELSE
指令序列 2
ENDIF
IF 、ELSE 、ENDIF偽指令能根據條件的成立與否決定是否執行某個指令序列。當IF后面的邏輯表達式為真,則執行指令序列1 ,否則執行指令序 列2 。其中,ELSE及指令序列2可以沒有,此時,當IF后面的邏輯表達式為真,則執行指令序列1 ,否則繼續執行后面的指令。
IF 、ELSE 、ENDIF偽指令可以嵌套使用。
使用示例:
GBLL Test ;聲明一個全局的邏輯變量,變量名為Test
IF Test = TRUE
指令序列 1
ELSE
指令序列 2
ENDIF
B、WHILE、WEND
語法格式:
WHILE 邏輯表達式
指令序列
WEND
WHILE 、WEND偽指令能根據條件的成立與否決定是否循環執行某個指令序列。當WHILE后面的邏輯表達式為真,則執行指令序列,該指令序列執行完畢后,再判斷 邏輯表達式的值,若為真則繼續執行,一直到邏輯表達式的值為假。
WHILE 、WEND偽指令可以嵌套使用。
使用示例:
GBLA Counter ; 聲明一個全局的數學變量,變量名為Counter
Counter SETA 3 ;由變量Counter 控制循環次數
……
WHILE Counter < 10
指令序列
WEND
C、MACRO、MEND、MEXIT
語法格式:
MACRO
[$ 標號]宏名[$ 參數 1 ,$ 參數 2 ,……]
語句段
MEXIT
D、MEXIT
語法格式:
MEXIT
MEXIT用于從宏定義中跳轉出去。
4、其他偽指令
A、AREA
語法格式:
AREA 段名 屬性1 ,屬性2 ,……
AREA偽指令用于定義一個代碼段或數據段。其中,段名若以數字開頭,則該段名需用“|”括起來,如:|1_test| 。
屬性字段表示該代碼段(或數據段)的相關屬性,多個屬性用逗號分隔。常用的屬性如下:
— CODE 屬性:用于定義代碼段,默認為READONLY 。
— DATA 屬性:用于定義數據段,默認為READWRITE 。
— READONLY 屬性:指定本段為只讀,代碼段默認為READONLY 。
— READWRITE 屬性:指定本段為可讀可寫,數據段的默認屬性為READWRITE 。
— ALIGN 屬性:使用方式為ALIGN表達式。在默認時,ELF(可執行連接文件)的代碼段和數據段是按字對齊的,表達式的取值范圍為0~31,相應的對齊方式為2 表達式次方。
— COMMON 屬性:該屬性定義一個通用的段,不包含任何的用戶代碼和數據。各源文件中同名的COMMON段共享同一段存儲單元。
一個匯編語言程序至少要包含一個段,當程序太長時,也可以將程序分為多個代碼段和數據段。
使用示例:
AREA Init ,CODE ,READONLY ; 該偽指令定義了一個代碼段,段 名為Init ,屬性為只讀。
B、ALIGN
語法格式:
ALIGN { 表達式 { ,偏移量 }}
ALIGN偽指令可通過添加填充字節的方式,使當前位置滿足一定的對齊方式。其中,表達式的值用于指定對齊方式,可能的取值為2的冪,如1 、2 、4 、8 、16 等。若未指定表達式,則將當前位置對齊到下一個字的位置。偏移量也為一個數字表達式,若使用該字段,則當前位置的對齊方式為:2的表達 式次冪+偏移 量。
使用示例:
AREA Init ,CODE ,READONLY ,ALIEN=3 ;指定后面的指令為8 字節對齊。
指令序列
END
C、CODE16、CODE32
語法格式:
CODE16(或CODE32)
CODE16偽指令通知編譯器,其后的指令序列為16位的Thumb指令。
CODE32偽指令通知編譯器,其后的指令序列為32位的ARM指令。
若 在匯編源程序中同時包含ARM指令和Thumb指令時,可用CODE16偽指令通知編譯器其后的指令序列為16位的Thumb指令,CODE32偽指 令 通知編譯器其后的指令序列為32位的ARM指令。因此,在使用ARM指令和Thumb指令混合編程的代碼里,可用這兩條偽指令進行切換,但注意他們只 通知 編譯器其后指令的類型,并不能對處理器進行狀態的切換。
使用示例:
AREA Init ,CODE ,READONLY ……
CODE32 ; 通知編譯器其后的指令為32位的 ARM指令
LDR R0 ,=NEXT+1 ;將跳轉地址放入寄存器R0
BX R0 ; 程序跳轉到新的位置執行, 并將處理器切換到Thumb工作狀態
……
CODE16 ; 通知編譯器其后的指令為16位的 Thumb指令
NEXT LDR R3,=0x3FF
……
END ;
D、ENTRY
語法格式:
ENTRY
ENTRY偽指令用于指定匯編程序的入口點。在一個完整的匯編程序中至少要有一個ENTRY(也可以有多個,當有多個ENTRY時,程序的真正入口點由鏈 接器指定),但在一個源文件里最多只能有一個ENTRY(可以沒有)。
使用示例:
AREA Init ,CODE ,READONLY
ENTRY ; 指定應用程序的入口點
……
E、END
語法格式:
END
END偽指令用于通知編譯器已經到了源程序的結尾。
使用示例:
AREA Init ,CODE ,READONLY
……
END ;指定應用程序的結尾
F、EQU
語法格式:
名稱 EQU 表達式 { ,類型 }
EQU偽指令用于為程序中的常量、標號等定義一個等效的字符名稱,類似于C語言中的#define 。其中EQU可用“*”代替。名稱為EQU偽指令定義的字符名稱,當表達式為32位的常量時,可以指定 表達式的數據類型,可以有以下三種類型:
CODE16 、CODE32 和DATA
使用示例:
Test EQU 50 ; 定義標號Test 的值為50。
Addr EQU 0x55 ,CODE32 ; 定義Addr的值為0x55 ,且該處為32位的ARM指令。
G、EXPORT(或GLOBAL)
語法格式:
EXPORT 標號 {[WEAK]}
EXPORT偽指令用于在程序中聲明一個全局的標號,該標號可在其他的文件中引用。EXPORT 可用GLOBAL代替。標號在程序中區分大小寫,[WEAK] 選項聲明其他的同名標號優先于該標號被引用。
使用示例:
AREA Init ,CODE ,READONLY
EXPORT Stest ;聲明一個可全局引用的標號Stest
END
H、IMPORT
語法格式:
IMPORT 標號 {[WEAK]}
IMPORT偽指令用于通知編譯器要使用的標號在其他的源文件中定義,但要在當前源文件中引用,而且無論當前源文件是否引用該標號,該標號均會被加入到當 前源文件的符號表中。標 號在程序中區分大小寫,[WEAK] 選項表示當所有的源文件都沒有定義這樣一個標號時,編譯器也不給出錯誤信息,在多數情況下 將該標號置為0 ,若該標號為B或BL指令引用,則將B或BL指令置為NOP操作。
使用示例:
AREA Init ,CODE ,READONLY
IMPORT Main ;通知編譯器當前文件要引用標號Main,但Main在其他源文件中定 義。
END
I、EXTERN
語法格式:
EXTERN 標號 {[WEAK]}
EXTERN偽指令用于通知編譯器要使用的標號在其他的源文件中定義,但要在當前源文件中引用,如果當前源文件實際并未引用該標號,該 標號就不會被加入 到當前源文件的符號表中。標號在程序中區分大小寫, [WEAK] 選項表示當所有的源文件都沒有定義這樣一個標號時,編譯器也不給出錯誤信息,在多數情 況下將該標號置為0 ,若該標號為B或BL指令引用,則將B或BL指令置為NOP操作。
使用示例:
AREA Init ,CODE ,READONLY
EXTERN Main ;通知編譯器當前文件要引用標號Main,但Main在其他源文件中定 義。
END
J、GET(或INCLUDE)
語法格式:
GET 文件名
GET偽指令用于將一個源文件包含到當前的源文件中,并將被包含的源文件在當前位置進行匯編處理。可 以使用INCLUDE代替GET。
匯編程序中常用的方法是在某源文件中定義一些宏指令,用EQU定義常量的符號名稱,用MAP和FIELD定義結構化的數據類型,然后用GET偽指令將這個 源文件包含到其他的源文件中。使用方法與C 語言中的"include” 相似。
GET偽指令只能用于包含源文件,包含目標文件需要使用INCBIN偽指令
使用示例:
AREA Init ,CODE ,READONLY
GET a1.s ; 通知編譯器當前源文件包含源文件a1.s
GET C:\a2.s ; 通知編譯器當前源文件包含源文件C:\a2.s
END
K、INCBIN
語法格式:
INCBIN 文件名
INCBIN偽指令用于將一個目標文件或數據文件包含到當前的源文件中,被包含的文件不作任何變動的存放在當前文件中,編譯器從其后開始繼續處理。
使用示例:
AREA Init ,CODE ,READONLY
INCBIN a1.dat ; 通知編譯器當前源文件包含文件a1.dat
INCBIN C:\a2.txt ;通知編譯器當前源文件包含文件C:\a2.txt
END
L、RN
語法格式:
名稱 RN 表達式
RN偽指令用于給一個寄存器定義一個別名。采用這種方式可以方便程序員記憶該寄存器的功能。其中,名稱為給寄存器定義的別名,表達式為寄存器的編碼。
使用示例:
Temp RN R0 ;將R0定義一個別名Temp
M、ROUT
語法格式:
{名稱} ROUT
ROUT偽指令用于給一個局部變量定義作用范圍。在程序中未使用該偽指令時,局部 變量的作用范圍為所在的AREA,而使用ROUT后,局部變量的作為范圍為當前ROUT和下一個ROUT之間。
嵌入式arm匯編指令這是最全的了,都記住了嗎?記不住也沒事,收藏起來可以備以后來使用,但是必須要理解才行。