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彙程式設計式設計 |