天天看點

ARM彙編語言僞指令

ARM彙編語言僞指令 2009-04-14 14:47 http://hi.baidu.com/%CF%EB%B7%C9%B5%C4%B4%FC%CA%F3/blog/item/ba6e93cb867a9e17be09e68e.html

ARM彙編語言僞指令

ARM中僞指令不是真正的ARM指令或者Thumb指令,這些僞指令在彙編編譯時對源程式進行彙編處理時被替換成對應的ARM或Thumb指令(序列)。ARM僞指令包括ADR、ADRL、LDR和NOP等。

1、ADR(小範圍的位址讀取僞指令)

該指令将基于PC的位址值或基于寄存器的位址值讀取到寄存器中。

文法格式

ADR{cond} register, expr

其中,cond為可選的指令執行的條件

      register為目标寄存器

      expr為基于PC或者基于寄存器的位址表達式,其取值範圍如下:

當位址值不是字對齊時,其取值範圍為-255~255.

當位址值是字對齊時,其取值範圍為-1020~1020

當位址值是16位元組對齊時,其取值範圍将更大

在彙編編譯器處理源程式時,ADR僞指令被編譯器替換成一條合适的指令。通常,編譯器用一條ADD指令或SUB指令來實作該ADR僞指令的功能。

因為ADR僞指令中的位址是基于PC或者基于寄存器的,是以ADR讀取到的位址為位置無關的位址。當ADR僞指令中的位址是基于PC時,該位址與ADR僞指令必須在同一個代碼段中。

示例

start MOV r0,#10 ;因為PC值為目前指令位址值加8位元組

ADR r4, start ;本ADR僞指令将被編譯器替換成SUB r4,pc,#0xc

2、 ADRL(中等範圍的位址讀取僞指令)

該指令将基于PC或基于寄存器的位址值讀取到寄存器中。ADRL僞指令比ADR僞指令可以讀取更大範圍的位址。ADRL僞指令在彙編時被編譯器替換成兩條指令,即使一條指令可以完成該僞指令的功能。

文法格式

ADRL{cond} register,expr

示例

start MOV r0,#10 ;因為PC值為目前指令位址值加8位元組

ADRL r4,start+60000 ;本ADRL僞指令将被編譯器替換成下面兩條指令

ADD r4,pc,#0xe800

ADD r4,r4,#0x254

3、LDR(大範圍的位址讀取僞指令)

LDR僞指令将一個32位的常數或者一個位址值讀取到寄存器中

文法格式

LDR{cond} register, =[expr|label-expr]

其中,expr為32位的常量。編譯器将根據expr的取值情況,如下處理LDR僞指令:

當expr表示的位址值沒有超過MOV或MVN指令中位址的取值範圍時,編譯器用合适的MOV或MVN指令代替該LDR僞指令

當expr表示的位址值超過了MOV或者MVN指令中位址的取值範圍時,編譯器将該常數放在資料緩沖區中,同時用一條基于PC的LDR指令讀取該常數。

label-expr為基于PC的位址表達式或者是外部表達式。當label-expr為基于PC的位址表達式時,編譯器将label-expr表示的數值放在資料緩沖區(literal pool)中,然後将該LDR僞指令處理成一條基于PC到該資料緩沖區單元的LDR指令,進而将該位址值讀取到寄存器中。這時,要求該資料緩沖區單元到PC的距離小于4KB。當label-expr為外部表達式,或者非目前段的表達式時,彙編編譯器将在目标檔案中插入一個位址重定位僞操作,這樣連接配接器将在連接配接時生成該位址。

LDR僞指令主要有以下兩種用途:

當需要讀取到寄存器中的資料超過了MOV及MVN指令可以操作的範圍時,可以使用LDR僞指令将該資料讀取到寄存器中。

将一個基于PC的位址值或者外部的位址值讀取到寄存器中。由于這種位址值是在連接配接時确定的,是以這種代碼不是位置無關的。同時LDR僞指令的PC值到資料緩沖區中的目标資料所在的位址的偏移量要小于4KB。

示例

将0xff0讀取到R1中

LDR R1,=0xFF0

彙編後将得到:

MOV R1,0xFF0

将0xfff讀取到R1中

LDR R1,=0xFFF

彙編後将得到:

LDR R1,[PC,OFFSET_TO_LPOOL]

LPOOL DCD 0xFFF

将外部位址ADDR1讀取到R1中

LDR R1,=ADDR1

彙編後将得到:

LDR R1,[PC,OFFSET_TO_LPOOL]

LPOOL   DCD ADDR1

4、NOP空操作僞指令

在彙編時将被替換成ARM中的空操作,如MOV R0,R0

NOP僞指令不影響CPSR中的條件标志位

ARM彙程式設計式中的符号

在ARM彙編語言中,符号(symbols)可以代表位址(addresse)、變量(variables)和數字常量(numeric constants)。當符号代表位址時,又稱為标号(lable)。當标号以數字開頭時,其作用範圍為目前段(目前段沒有使用ROUT僞操作時),這種标号又稱為局部标号(lacal lable)。符号變量包括變量、數字常量、标号和局部标号。

1、變量

在程式中,變量的值在彙編處理過程中可能會發生改變。在ARM彙編中變量有數字變量、邏輯變量和串變量3種類型。變量的類型在程式中是不可以改變的。

數字變量的取值範圍為數字常量和數字表達式所能表示的數值;邏輯變量的取值範圍為{true}和{flash};串變量的取值範圍為串表達式可以表達的範圍。

在ARM彙編語言中,使用GBLA、GBLL及GBLS聲明全局變量;使用LCLA、LCLL及LCLS聲明局部變量;使用SETA、SETL及SETS為這些變量指派。

2、數字常量

數字常量是32位的整數。在ARM彙編語言中,使用EQU來定義數字常量。數字常量一經定義就不可修改。 進行大小比較時,認為數字常量都是無符号數。

3、彙編時變量的替換

如果在串變量前有一個$字元,在彙編時編譯器将用改串的數值來取代該串變量。

對于數字變量來說,如果該變量前面有一個$字元,在彙編時編譯器将該數字變量的數值轉換成十六進制的串,然後用該十六進制的串取代$字元後的數字變量。

對于邏輯變量來說,如果該邏輯變量前面有一個$字元,在彙編時編譯器将該邏輯變量替換成它的取值(T或者F)

如果程式中需要字元$,則用$$來表示,編譯器将不進行變量替換,而是将$$當作$.

通常情況下,包含在兩個豎線(|)之間的$并不表示進行變量替換。但是如果豎線(|)是在雙引号内,則将進行變量替換。

使用“.”來表示變量名稱的結束。

4、标号

标号是表示程式中的指令或者資料位址的符号。根據标号的生成方式可分為3種:

基于PC的标号。基于PC的标号是位于目标指令前或者程式中資料定義僞操作前的标号。這種标号在彙編時将被處理成PC值加上(或減去)一個數字常量。常用于表示跳轉指令的目标位址,或者代碼段中所嵌入的少量資料。

基于寄存器的标号。基于寄存器的标号常用MAP和FIELD未定義操作,也可以該用EQU僞定義。這種标号在彙編時将被處理成寄存器的值加上(或減去)一個資料常量。常用于通路資料段中的資料。

絕對位址。絕對位址是一個32位資料。它可以尋址232 -1,即直接可以尋址整個記憶體空間。

5、局部标号

局部标号主要在局部範圍内使用。它由兩部組成:開頭是一個0-99直接的數字,後面緊接一個通常表示該局部變量作用範圍的符号。

局部變量的作用範圍通常為目前段,也可以用僞操作ROUT來定義局部變量的作用範圍。

局部變量定義的文法格式如下:

N{routname},其中,N為0~99之間的數字。routname為符号,通常為該變量作用範圍的名稱(用ROUT僞操作定義的)。

局部變量引用的文法格式如下:

%{F|B}{A|T}N{routname}

其中,N為局部變量的數字号。

routname 為目前作用範圍的名稱(用ROUT僞操作定義的)

%表示引用操作

F訓示編譯器隻向前搜尋

B訓示編譯器隻向後搜尋

A訓示編譯器搜尋宏的所有嵌套層次

T訓示編譯器搜尋宏的目前層次

如果F和B都沒有指定,編譯器先向前搜尋,再向後搜尋

如果A和T都沒有指定,編譯器搜尋所有從目前層次到宏的最高層次,比目前層次低的層次不再搜尋。

如果指定了routname,編譯器向前搜尋最近的ROUT僞操作,若routname與該ROUT僞操作定義的名稱不比對,編譯器報告錯誤,彙編失敗。

ARM彙編語言中的表達式

表達式是由符号、數值、單目或多目操作符以及括号組成的。

1、字元串表達式

字元串表達式由字元串、字元串變量、操作符以及括号組成。字元串的最大長度為512位元組,最小長度為0.下面介紹字元串表達式的組成元素。

字元串:由包含在雙引号内的一系列的字元組成。字元串的長度受到ARM彙編語言語句長度的限制。當在字元串中包含美元符号$或者引号"時,用$$表示一個$,用""表示一個"。

字元串變量:用僞操作GBLS或者LCLS聲明,用SETS指派。

操作符:

(1)LEN:傳回字元串的長度

:LEN:A

其中,A為字元串變量

(2)CHR:可以将0~255之間的整數作為含一個ASCII字元的字元串。當有些ASCII字元不友善放在字元串中時,可以使用CHR将其放在字元串表達式中。

:CHR:A

其中,A為某一字元的ASCII值

(3)STR:将一個數字量或者邏輯表達式轉換成串。對于32位的數字量而言,STR将其轉換成8個十六進制數組成的串;對于邏輯表達式而言,STR将其轉換成字元串T或者F

:STR:A

其中,A為數字量或者邏輯表達式

(4)LEFT:傳回一個字元串最左端一定長度的子串

A:LEFT:B

其中,A為源字元串,B為數字量,表示LEFT将傳回的字元個數

(5)RIGHT:傳回一個字元串最右端一定長度的子串

A:RIGHT:B

其中,A為源字元串,B為數字量,表示RIGHT将傳回的字元個數

(6)CC:用于連接配接兩個字元串。

A:CC:B

其中,A為第1個源字元串。B為第2個源字元串。CC操作符将字元串B連接配接在字元串A的後面。

2、數字表達式

數字表達式由數字常量、數字變量、操作符和括号組成

數字變量用僞操作GBLA或者LCLA聲明,用SETA指派,它代表一個32位的數字量。

操作符:

(1)NOT:按位取反

:NOT:A

其中,A為一個32位數字量

(2)+、—、×、/及MOD算術操作符

A+B,A-B,A×B,A/B

A:MOD:B表示A除以B的餘數

(3)ROL,ROR,SHL,SHR移位

A:ROL:B将整數A循環左移B位

A:SHL:B将整數A左移B位

(4)AND、OR及EOR按位邏輯操作符

A:AND:B将數字表達式A和B按位作邏輯與操作

3、基于寄存器和基于PC的表達式

基于寄存器的表達式表示了某個寄存器的值加上(或者減去)一個數字表達式

基于PC的表達式表示了PC寄存器的值加上(或減去)一個數字表達式。基于PC的表達式通常由程式中的标号與一個數字表達式組成。相關的操作符:

(1)BASE:傳回基于寄存器的表達式中的寄存器編号。

:BASE:A    A為基于寄存器的表達式

(2)INDEX:傳回基于寄存器的表達式相對于其基址寄存器的偏移量。

:INDEX:A   A為基于寄存器的表達式

(3)+、﹣:正負号,可以放在數字表達式或者基于PC的表達式前面。

+A(﹣A)   A為基于PC的表達式或者數字表達式

4、邏輯表達式

由邏輯量、邏輯操作符、關系操作符以及括号組成,取值範圍為{FLASE}和{TRUE}

關系操作符:用于表示兩個同類表達式之間的關系。關系操作符和它的兩個操作數組成一個邏輯表達式,其取值為{FALSE}或{TRUE}

如A=B 表示A等于B

A/=B,A<>B表示A不等于B

邏輯操作符:進行兩個邏輯表達式之間的基本邏輯操作。操作的結果為{FLASE}或{TRUE}

:LNOT:A 邏輯表達式A的值取反

A:LAND:B邏輯表達式A和B邏輯與

5、其他的一些操作符

(1)?:傳回定義符号A的代碼行所生成的可執行代碼的位元組數

?A

其中,A為一個符号

(2)DEF:判斷某個符号是否已定義

:DEF:A

如果符号A已經定義,上述結果為{TRUE},否則為{FLASE}

(3)SB_OFFSET_19_12

:SB_OFFSET_19_12:label 其中,label為一個标号

傳回(label-SB)的bits[19:12]

(4)SB_OFFSET_11_0

:SB_OFFSET_11_0:label

傳回(label-SB)的bits[11:0]

注:可以參照ADS目錄下的examples中的例子程式了解ARM彙程式設計式設計

繼續閱讀