1. 程式人生 > >常用的ARM彙編指令

常用的ARM彙編指令

一. 帶點的(一般都是ARM GNU偽彙編指令)

 

1. ".text"、".data"、".bss"

依次表示的是

“以下是程式碼段”,

“以下是初始化資料段”,

“以下是未初始化資料段”。

2.".global"

定義一個全域性符號,通常是為ld使用。比如經常看到的

.global _start

3.".ascii"、".byte"、".short"、".int"、".long"、".word"、".quad"

定義一個字串,併為它分配空間

定義一個位元組,併為它分配空間,佔單位元組,0x34

定義一個短整型,併為它分配空間,佔雙位元組,0x1234

定義一個整型,併為它分配空間,佔四位元組,0x12345678

定義一個長整型,併為它分配空間,佔四位元組,0x12345678

定義一個字,併為它分配空間,

定義一個,併為它分配定義,佔八位元組,...

比如
.long 0x22011110//BWSCON
.long 0x00000700//BANKCON0
...

 

4.".abort"

停止彙編

5.".align"

.align absexpr1,absexpr2

以某種對齊方式,在未使用的儲存區域填充值. 第一個值表示對齊方式,4, 8,16或32. 第二個表示式值表示填充的值

6.".if .else .endif"

.if

.else

.endif:支援條件預編譯

7.".include"

.include "file":包含指定的標頭檔案, 可以把一個彙編常量定義放在標頭檔案中

8.".comm"

 

.comm  symbol, length:

在bss段申請一段名稱空間,該段空間的名稱叫symbol, 長度為length. Ld聯結器在連線會為它留出空間

9.".equ"

.equ symbol, expression: 把某一個符號(symbol)定義成某一個值(expression).該指令並不分配空間,相當於C語言中的#define。例如

.equ aaa,0x20000000

10.".macro .endm"

.macro: 定義一段巨集程式碼,.macro表示程式碼的開始,.endm表示程式碼的結束,.exitm跳出巨集, 示例如下:

.macro SHIFTLEFT a, b.if \b < 0

mov \a, \a, ASR #-\b

.exitm

.endif

mov \a, \a, LSL #\b

.endm

11.".req"

name .req register name: 為暫存器定義一個別名

12.".code"

.code [16|32]: 指定指令程式碼產生的長度, 16表示Thumb指令, 32表示ARM指令

13.".ltorg"

.ltorg: 表示當前往下的定義在歸於當前段,併為之分配空間

 

二.帶下滑線的

1._start

彙編程式的預設入口,但是可以更改,想要更改其他標誌,到相應的連結指令碼中去用ENTRY指明其他入口標誌。標號可以直接認為是地址。

三.不帶點的

1.mov--資料傳送指令

它的傳送指令只能是把一個暫存器的值(要能用立即數表示)賦給另一個暫存器,或者將一個常量賦給暫存器,將後邊的量賦給前邊的量,比如

mov r1,r2

mov r1,#4096

這個立即數是小於0xff(65535)的數,如果大於65535,則用ldr指令賦值

2.b、bl--相對跳轉指令

b只是跳轉,而bl除跳轉外還將返回地址(bl的下一條指令的地址)儲存到lr暫存器中。其中跳轉範圍是當前指令的前後32M。

3.ldr、str--記憶體訪問指令

ldr指令即可能是大範圍的地址讀取偽指令,也可能是記憶體訪問指令,當它的第二個引數之前有“=”時,表示偽指令,否則是記憶體訪問指令,比如

ldr r0, =0x53000000//r0=0x53000000

str r1, [r2, #4]         // 將r1的資料儲存到地址為r2+4的記憶體單元中

str r1, [r2]                // 將r1的資料儲存到地址為r2的記憶體單元中

str r1, [r2], #4         // 將r1的資料儲存到地址為r2的記憶體單元中,然後r2=r2+4

ldr r1, [r2,#4]         // 將地址為r2+4的記憶體單元資料讀取到r1中

ldr r1, [r2]             // 將地址為r2的記憶體單元資料讀取到r1中

ldr r1, [r2], #4         // 將地址為r2的記憶體單元資料讀取到r1中,然後r2=r2+4

作為變址方式有如下分類:

當ldr作為大範圍地址讀取偽指令,LDR偽指令用於載入32們的立即數或一個地址值到指定暫存器。在彙編編譯源程式時,LDR偽指令被編譯器替換成一條合適的指令。若載入的常數未超出MOV或者MVN的範圍,剛使用MOV或MVN指令代替該LDR偽指令,否則彙編器將常量放入字池,並使用一 條程式相對偏移的LDR指令從文字池讀出常量。

作為暫存器的定址,暫存器的間接定址的3種方式

4.adr--小範圍的地址讀取(只有兩個引數)

ADR指令將基於PC相對偏移的地址值讀取到暫存器中,在編譯源程式時ADR偽指令被編譯器替換成一條合適的指令。通常,編譯器用一條ADD指令或SUB指令來實現該ADR偽指令的功能,若不能用一條指令實現,剛產生錯誤,編譯失敗。比如

adr r0, delay//將標號delay的地址賦給r0

5.ldmia--多暫存器定址

一條指令可以完成多個暫存器值的傳遞,可以完成最多16個通用暫存器值的傳遞。比如

ldmia r0, [r1, r2, r3, r4]

;r1 <- [r0]

;r2 <- [r0+4]

;r3 <- [r0+4*2]

;r4 <- [r0+4*3]

6.nop--空操作指令

什麼都不做,可以用作延時。

7.add,sub--加法減法指令

共三個引數,將後邊的兩個引數操作並賦給第一個引數,比如

add r1, r1, r0//r1=r1+r0

sub r1, r1, r2//r1=r1-r2

//這兩句的結果就是r1=r1+r0-r2

8.asr,lsl,lsr,ror,rrx,type rs

對於arm指令的基本格式如下:

對於operand2引數,如果能靈活使用,程式碼效率會很高。

桶型一位暫存器操作

9.cmp--比較指令

cspr

10.eq,ne,ce等--指令的條件域

所有的ARM指令都可以條件執行:指令的執行與否取決於CPSR暫存器的N,Z,CandV
每一條ARM指令包含4位的條件碼位於指令的最高4位[31:28],條件碼共16種,每個條件碼可以用2個字元表示,這兩個字元可以新增在指令助記符的後邊和指令同時使用。
指令最高4位代表的條件域如下表

條件碼

助記符字尾

標誌

含義

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

忽略

無條件執行

例如

cmp r0, r1

beq func//如果r1==r0,則跳轉到func標誌地址上去

 

cmp r0, r1

beq func//如果r1!=r0,則跳轉到func標誌地址上去

11.R13,R14暫存器--sp,lr

sp是堆疊指標,lr是連結地址暫存器。R13作為sp,R14作為lr。
對於連結地址暫存器,它的作用有兩個:

【1】當使用bl指令呼叫子程式時,系統會自動將 bl指令的下一條指令的地址存入lr中。

執行過程如下圖

①,程式A正常執行到BL Lable然後轉到程式B中去
②,系統將BL Lable的下一句NEXT的地址放到LR中去
③,執行完B的程式後,執行一個MOV PC,LR將NEXT的地址給到當前pc值
④,繼續執行程式A下面的語句

【2】當發生異常時,系統自動將異常的返回地址放入R14中(有些異常有一個小的固定的偏移量)。

 

12.邏輯運算指令--

 

;按位與

AND Rd, Rn                                 ; Rd &= Rn

AND.W Rd, Rn, #imm12           ; Rd = Rn & imm12

AND.W Rd, Rm, Rn                    ; Rd = Rm & Rn

 

;按位或

ORR Rd, Rn                                  ; Rd |= Rn

ORR.W Rd, Rn, #imm12            ; Rd = Rn | imm12

ORR.W Rd, Rm, Rn                     ; Rd = Rm | Rn

 

;按位清零

BIC Rd, Rn                                    ; Rd &= ~Rn

BIC.W Rd, Rn, #imm12             ; Rd = Rn & ~imm12

BIC.W Rd, Rm, Rn                      ; Rd = Rm & ~Rn

 

;按位或反

ORN.W Rd, Rn, #imm12          ; Rd = Rn | ~imm12

ORN.W Rd, Rm, Rn                   ; Rd = Rm | ~Rn

 

;按位異或

EOR Rd, Rn                                 ; Rd ^= Rn

EOR.W Rd, Rn, #imm12           ; Rd = Rn ^ imm12

EOR.W Rd, Rm, Rn                    ; Rd = Rm ^ Rn

 

;邏輯左移

LSL Rd, Rn, #imm5                  ; Rd = Rn<<imm5

LSL Rd, Rn                                 ; Rd <<= Rn

LSL.W Rd, Rm, Rn                   ; Rd = Rm<<Rn

 

;邏輯右移

LSR Rd, Rn, #imm5                ; Rd = Rn>>imm5

LSR Rd, Rn                               ; Rd >>= Rn

LSR.W Rd, Rm, Rn                  ; Rd = Rm>>Rn

 

;算術右移

ASR Rd, Rn, #imm5                 ; Rd = Rn>> imm5

ASR Rd, Rn                                ; Rd =>> Rn

ASR.W Rd, Rm, Rn                   ; Rd = Rm>>Rn

 

;迴圈右移

ROR Rd, Rn ;

ROR.W Rd, Rm, Rn ;

 

四.彙編中的註釋

(1) @ 表示註釋從當前位置到行尾的字元.

(2) # 註釋掉一整行.

(3) ; 新行分隔符.

五.彙編中的常數

(1)十進位制數以非0數字開頭,如:123和9876;

(2)二進位制數以0b開頭,其中字母也可以為大寫; 

(3)八進位制數以0開始,如:0456,0123;

(4)十六進位制數以0x開頭,如:0xabcd,0X123f;

(5)字串常量需要用引號括起來,中間也可以使用轉義字元,如: “You are welcome!/n”;

(6)當前地址以“.”表示,在彙編程式中可以使用這個符號代表當前指令的地址;

(7)表示式:在彙編程式中的表示式可以使用常數或者數值, “-”表示取負數, “~”表示取補,“<>”表示不相等,其他的符號如:+、-、*、/、%、<、<<、>、>>、|、&、^、!、==、>=、<=、&&、||跟C語言中的用法相似。

六.彙編程式較好的格式

 

轉載自https://blog.csdn.net/qq_27522735/article/details/75043870