ARM彙編僞指令

ARM 彙編程序的由機器指令,僞指令和宏指令組成。僞指令不像機器指令那樣在處理器運行期間由機器執行,而是彙編程序對源程序彙編期間由彙編程序處理。在前面的指令集章節中,我們已經接觸了幾條常用到的僞指令,如ADR 、ADRL、LDR、NOP 等,把它們和指令集一起介紹是因爲它們在彙編時會被合適的機器指令代替,實現真正機器指令操作。宏是一段獨立的程序代碼,它是通過僞指令定義的,在程序中使用宏指令即可調用宏。
         當程序被彙編時,彙編程序將對每個調用進行展開,用宏定義取代源程序中的宏指令。

A.4.1  符號定義僞指令
         符號定義僞指令用於定義ARM 彙編程序的變量,對變量進行賦值以及定義寄存器名稱,該類僞指令如下:
                  全局變量聲明:GBLA、GBLL 和GBLS。
                  局部變量聲明:LCLA、LCLL 和LCLS。
                  變量賦值: SETA、SETL 和SETS。
                  爲一個通用寄存器列表定義名稱:RLIST。
                  爲一個協處理器的寄存器定義名稱:CN。
                  爲一個協處理定義名稱: CP。
                  爲一個VFP 寄存器定義名稱:DN 和SN。
                  爲一個FPA 浮點寄存器定義名稱:FN。

         GBLA、GBLL、GBLS
         全局變量聲明僞指令。
         GBLA 僞指令用於聲明一個全局的算術變量,並將其初始化爲0。
         GBLL 僞指令用於聲明一個全局的邏輯變量,並將其初始化爲{FALSE}。
         GBLS 僞指令用於聲明一個全局的字符串變量,並將其初始化爲空字符串“”。
         僞指令格式:
         GBLA variable
         GBLL variable
         GBLS variable
         其中:variable 定義的全局變量名,在其作用範圍內必須惟一。全局變量的作用範圍爲包含該變量的源程序。
         僞指令應用舉例如下:
         GBLL codedbg ;聲明一個全局邏輯變量
         codebg SETL {TRUE} ;設置變量爲{TRUE}
         …

         LCLA、LCLL、LCLS
         局部變量聲明僞指令,用於宏定義的體中。
         LCLA 僞指令用於聲明一個局部的算術變量,並將其初始化爲0。
         LCLL 僞指令用於聲明一個局部的邏輯變量,並將其初始化爲{FALSE}。
         LCLS 僞指令用於聲明一個局部的字符串變量,並將其初始化爲空字符串“”。
         僞指令格式:
         LCLA variable
         LCLL variable
         LCLS variable
         其中:variable 定義的局部變量名。在其作用範圍內必須惟一。局部變量的作用範圍爲包含該局部變量只能在宏中進行聲明及使用。
         僞指令應用舉例如下:
         MACRO ;聲明一個宏
         SENDDAT $dat ;宏的原型
         LCLA bitno ;聲明一個局部算術變量
         …
         bitno SETA 8 ;設置變量值爲8
         …
         MEND

         SETA、SETL、SETS
         變量賦值僞指令。用於對已定義的全局變量,局部變量賦值。
         SETA 僞指令用於給一個全局/局部的算術變量賦值。
         SETL 僞指令用於給一個全局/局部的邏輯變量賦值。
         SETS 僞指令用於給一個全局/局部的字符串變量賦值。
         僞指令格式:
         variable_a SETA expr_a
         variable_l SETL expr_l
         variable_s SETS expr_s
         其中:variable_a 算術變量。用GBLA、LCLA 僞指令定義的變量。
         expr_a 賦值的常數。
         variable_l 邏輯變量。用GBLL、LCLL 僞指令定義的變量。
         expr_l 邏輯值,即{TRUE}或{FALSE}。
         variable_s 字符串變量。用GBLS、LCLS 僞指令定義的變量。
         expr_s 賦值的字符串。
         僞指令應用舉例如下:
         GBLS ErrStr
         …
         ErrStr SETS “No,semaphone”
         …

         RLIST
         RLIST 爲一個通用寄存器列表定義名稱。僞指令格式如下:
         name RLIST {reglist}
         其中:name 要定義的寄存器列表的名稱。
         reglist 通用寄存器列表。
         僞指令應用舉例如下:
         LoReg RLIST {R0-R7} ;定義寄存器列表LoReg
         …
         STMFD SP!,LoReg ;保存寄存器列表LoReg
         …

         CN
         CN 爲一個協處理器的寄存器定義名稱。
         僞指令格式:
         name CN expr
         其中:name 要定義的協處理器的寄存器名稱。
         expr 協處理器的寄存器編號,數值範圍爲0~15。
         僞指令應用舉例如下:
         MemSet CN l ;將協處理的寄存器l 名稱定義爲MemSet

         CP
         CP 爲一個協處理器定義的名稱。
         僞指令格式:
         name CP expr
         其中:name 要定義的協處理器名稱。
         expr 協處理器的編號,數值範圍爲0~15。
         僞指令應用舉例如下:
         DivRun CN 5 ;將協處理器5 名稱定義爲DivRun

         DN、SN
         DN 和SN 爲VFP 的寄存器的名稱定義的僞指令。
         DN 爲一個雙精度原VFP 寄存器定義名稱。
         SN 爲一個單精度的VFP 寄存器定義名稱。
         僞指令格式:
         name DN expr
         name SN expr
         其中:name 要定義的VFP 寄存器名稱。
         expr 雙精度的VFP 寄存器編號爲0~15,單精度的VFP 寄存器編號爲0~31。
         僞指令應用舉例如下:
         cdn DN 1 ;將VFP 雙精度寄存器1 名稱定義爲cdn
         rex SN 3 ;將VFP 單精度寄存器3 名稱定義爲rex

         FN
         FN 爲一個FPA 浮點寄存器定義名稱
         僞指令格式:
         name FN expr
         其中:name 要定義的浮點寄存器名稱。
         expr 浮點寄存器的編號,值爲0~7。
         僞指令應用舉例如下:
         ibq FN l ;將浮點寄存器l 名稱定義爲ibq

A.4.2  數據定義僞指令
         數據定義僞指令用於數據表定義,文字池定義,數據空間分配等。該類僞指令如下:
         聲明一個文字池:LTORG。
         定義一個結構化的內存表的首地址:MAP。
         定義結構化內存表中的一個數據域:FIELD。
         分配一塊內存空間,並用0 初始化:SPACE。
         分配一段字節的內存單元,並用指定的數據初始化:DCB。
         分配一段字的內存單元,並用指令的數據初始化:DCD 和DCDU。
         分配一段字的內存單元,將每個單元的內容初始化爲該單元相對於靜態基址寄存器的偏移量:DCDO。
         分配一段雙字的內存單元,並用雙精度的浮點數據初始化:DCFD 和DCFDU。
         分配一段字的內存單元,並用單精度的浮點數據初始化:DCFS 和DCFSU。
         分配一段字的內存單元,並用單精度的浮點數據初始化,指定內存單元存放的是代碼,而不是數據:DCI。
         分配一段雙字的內存單元,並用64 位整數數據初始化:DCQ 和DCQU。
         分配一段半字的內存單元,並用指定的數據初始化:DCW 和DCWU。

         LTORG
         LTORG 用於聲明一個文字池,在使用LDR 僞指令時,要在適當的地址加入LTORG 聲明文字池,這樣就會把要加載的數據保存在文字池內,再用ARM 的加載指令讀出數據。(若沒有使用LTORG 聲明文字池,則彙編器會在程序末尾自動聲明。)
         僞指令格式:
         LTORG
         僞指令應用舉例如下:
         …
         LDR R0,=0x12345678
         ADD R1,R1,R0
         MOV PC,LR
         LTORG ;聲明文字池,此地址存儲0x12345678
         … ;其它代碼
         LTORG 僞指令常放在無條件跳轉指令之後,或者子程序返回指令之後,這樣處理器就不會錯誤地將文字池中的數據當作指令來執行。

         MAP
         MAP 用於定義一個結構化的內存表的首地址。此時,內存表的位置計數器{VAR}設置爲該地址值{VAR}爲彙編器的內置變量。^與MAP 同義。
         僞指令格式:
         MAP expr,{base_register}
         其中:expr 數字表達式或程序中的標號。當指令中沒有
         base_register 時,expr 即爲結構化內存表的首地址。
         base_register 一個寄存器。當指令中包含這一項時,結構化內存表的首地址爲expr 與base_register 寄存器值的和。
         僞指令應用舉例如下:
         MAP 0x00,R9 ;定義內存表的首地址爲R9
         Timer FIELD 4 ;定義數據域Timer,長度爲4 字節
         Attrib FIELD 4 ;定義數據域Attrib,長度爲4 字節
         String FIELD 100 ;定義數據域String,長度爲100 字節
         …
         ADR R9,DataStart ;設置R9 的值,即設置結構化的內存表地址
         LDR R0,Atrrib ;相當於LDR,R0,[R9,#4]
         …
         MAP 僞指令和FIELD 僞指令配合使用,用於定義結構化的內存表結構。MAP 僞指令中的base-register 寄存器的值對於其後所有的FIELD 僞指令定義的數據域是默認使用的,直到遇到新的包含base-register 項的MAP 僞指令。

         FIELD
         FIELD 用於定義一個結構化內存表中的數據域。#與FIELD 同義。
         僞指令格式:
         {tabel} FIELD expr
         其中:label 當指令中包含這一項時,label 的值爲當前內存表的位置計數器{VAR}的值,彙編編譯器處理了這條FIELD 僞指令後,內存表計數器的值將加上expr。
         expr 表示本數據域在內存表中所佔用的字節數。
         僞指令應用舉例如下:
         MAP 0x40003000 ;內存表的首地址爲0x40003000
         count1 FIELD 4 ;定義數據域count1,長度爲4 字節
         count2 FIELD 4 ;定義數據域count2,長度爲4 字節
         count3 FIELD 4 ;定義數據域count3,長度爲4 字節
         LDR R1,count1 ;R1=[0x40003000+0x00]
         STR R1,count2 ;[0x40003000+0x00]=R1
         MAP、FIELD 僞指令僅僅是定義數據結構,它們並不實際分配內存單元。

         SPACE
         SPACE 用於分配一塊內存單元,並用0 初始化。%與SPACE 同義。
         僞指令格式:
         {label} SPACE expr
         其中:label 內存塊起始地址標號。
         expr 所要分配的內存字節數。
         僞指令應用舉例如下:
         AREA DataRA,DATA,READWROTE ;聲明一數據段,名爲DataRAM
         DataBuf SPACE 1000 ;分配1000 字節空間

         DCB
         DCB 用於分配一段字節內存單元,並用僞指令中的expr 初始化。一般可用來定義數據表格,或文字符串。=與DCB 同義。
         僞指令格式:
         {label} DCB expr{,expr}{,expr}…
         其中:label 內存塊起始地址標號。
         expr 可以爲-128~255 的數值或字符串。內存分配的字節數由expr 個數決定。
         僞指令應用舉例如下
         DISPTAB DCB 0x33,0x43,0x76,0x12
         DCB -120,20,36,55
         ERRSTR DCB “Send,data is error!”,0

         DCD 和DCDU
         DCD 用於分配一段字內存單元,並用僞指令中的expr 初始化。DCD 僞指令分配的內存需要字對齊,一般可用來定義數據表格或其它常數。&與DCD 同義。
         DCDU 用於分配一段字內存單元,並用僞指令中的expr 初始化。DCD 僞指令分配的內存不需要字對齊,一般可用來定義數據表格或其它常數。
         僞指令格式:
         {label} DCD expr{,expr}{,expr}…
         {label} DCDU expr{,expr}{,expr}…
         其中:label 內存塊起始地址標號。
         expr 常數表達式或程序中的標號。內存分配字節數由expr 個數決定。
         僞指令應用舉例如下:
         Vectors
         LDR PC,ReserAddr
         LDR PC,UndefinedAddr
         …
         ResetAddr DCD Reset
         UndefinedAddr DCD Undefined
         …
         Reset
         …
         Undefined
         …

         DCDO
         DCDO 用於分配一段字內存單元。並將每個單元的內容初始化爲該單元相對於靜態基址寄存器的偏移量。DCDO 僞指令作爲基於靜態基址寄存器R9 的偏移量分配內存單元。DCDO 僞指令分配的內存需要字對齊。
         僞指令格式:
         {label} DCDO expr{,expr}{,expr}…
         其中:label 內存塊起始地址標號。
         expr 地址偏移表達式或程序中的標號。內存分配的字數由expr 個數決定。
         僞指令應用舉例如下:
         IMPORT externsym
         DCDO externsym ;分配32 位的字單元,其值爲標號externsym 基於R9 的偏移

         DCFD 和DCFDU
         DCFD 用於分配一段雙字的內存單元,並用雙精度的浮點數據fpliteral 初始化。每個雙精度的浮點數佔據兩個字單元。DCFD 僞指令分配的內存需要字對齊。
         DCFDU 具有DCFD 同樣的功能,但分配的內存不需要字對齊。
         僞指令格式:
         {label} DCFD fpliteral{,fpliteral}{,fpliteral}…
         {label} DCFDU fpliteral{,fpliteral}{,fpliteral}…
         其中:label 內存塊起始地址標號。
         fpliteral 雙精度的浮點數。
         僞指令應用舉例如下:
         DCFD 2E30,-3E-20
         DCFDU -.1,1000,2.1E18

         DCFS 和DCFSU
         DCFS 用於分配一段字的內存單元,並用單精度的浮點數據fpliteral 初始化。每個單精度的浮點數佔據一個字單元。DCFD 僞指令分配的內存需要字對齊。
         DCFSU 具有DCFS 同樣的功能,但分配的內存不需要字對齊。
         僞指令格式:
         {label} DCFS fpliteral{,fpliteral}{,fpliteral}…
         {label} DCFSU fpliteral{,fpliteral}{,fpliteral}…
         其中:label 內存塊起始地址標號
         fpliteral 單精度的浮點數。
         僞指令應用舉例如下:
         DCFS 1.1E2,-1.3E10,0.0999

         DCI
         在ARM 代碼中,DCI 用於分配一段字節的內存單元,用指定的數據expr 初始化。指定內存單元存放的是代碼,而不是數據。
         在Thumb 代碼中,DCI 用於分配一段半字節的內存單元,用指定的數據expr 初始化。指定內存單元存放的是代碼,而不是數據。
         僞指令格式:
         {label} DCI expr
         其中:label 內存塊起始地址標號。
         expr 可爲數字表達式。
         DCI 僞指令和DCD 僞指令非常類似,不同之處在於DCI 分配的內存中的數據被標識爲指令。可用於通過宏指令業定義處理器不支持的指令。
         僞指令應用舉例如下:
         MACRO ;宏定義(定義NEWCMN Rd,Rn 指令)
         NEWCMN $Rd,$Rm ;宏名爲NEWCMN,參數爲Rd 和Rm
         DCI 0xe16a0e20:OR:($Rd:SHL:12):OR:$Rm
         MEND

         DCQ 和DCQU
         DCQ 用於分配一段雙字的內存單元,並用64 位的整數數據literal 初始化。DCQ 僞指令分配的內存需要字對齊。
         DCQU 具有DCQ 同樣的功能,但分配的內存不需要字對齊。
         僞指令格式:
         {label} DCQ {-}literal{,{-}{literal}}…
         {label} DCQU {-}literal{,{-}{literal}}…
         其中:label 內存塊起始地址標號。
         literal 64 位的數字表達式。取值範圍爲0~264-1 當literal前有“.”號時,取值範圍爲-263~-1 之間。
         僞指令應用舉例如下:
         DCQU 1234,-76568798776

         DCW 和DCWU
         DCW 用於分配一段字的內存單元,並用指定的數據expr 初始化。DCW 僞指令分配的內存需要字對齊。
         DCWU 具有DCW 同樣的功能,但分配的內存不需要字對齊。
         僞指令格式:
         {label} DCW expr{,expr}{,expr}…
         {label} DCWU expr{,expr}{,expr}…
         其中:label 內存塊起始地址標號。
         expr 數字表達式,取值範圍爲-32768~65535。
         僞指令應用舉例如下:
         DCW -592,123,6756
         報告僞指令
         報告僞指令用於彙編報告指示。該類僞指令如下:
         斷言錯誤:ASSERT。
         彙編診斷信息顯示:INFO。
         設置列表選項:OPT。
         插入標題:TTL 和SUBT。

         ASSERT
         ASSERT 爲斷言錯誤僞指令。在彙編編譯器對彙編程序的第二遍掃描中,如果其中
         ASSERT 條件不成立,ASSERT 僞指令將報告該錯誤信息。
         僞指令格式:
         ASSERT Logical_expr
         其中:Logical_expr 用於斷言的邏輯表達式
         僞指令應用舉例如下:
         ASSERT Top<>Temp ;斷言Top 不等於Temp

         INFO
         彙編診斷信息顯示僞指令,在彙編器處理過程中的第一遍掃描或第一遍掃描時報告診斷信息。
         僞指令格式:
         INFO numeric_expr,string_expr
         其中:numeric_expr 數據表達式。若值爲0,則在第一遍掃描時報告診斷信息。否則在第一遍掃描時報告診斷信息。
         strint_expr 要顯示的字串
         僞指令應用舉例如下:
         INFO 0,”Version 0。1” ;在第二遍掃描時,報告版本信息
         if cont1 > cont2 ;如果cont1 > cont2
         INFO 1,”cont1 > cont2” ;則在第一遍掃描時報告”cont1 > cont2”

         OPT
         設置列表選項僞指令。通過OPT 僞指令可以在源程序中設置列表選項。
         僞指令格式:
         OPI n
         其中n 所設置的選項的編碼如下:
         1 設置常規列表選項
         2 關閉常規列表選項
         4 設置分頁符,在新的一頁開始顯示
         8 將行號重新設置爲0
         16 設置選項,顯示SET、GBL、LCL 僞指令
         32 設置選項,不顯示SET、GBL、LCL 僞指令
         64 設置選項,顯示宏展開
         128 設置選項,不顯示宏展開
         256 設置選頂,顯示宏調用
         512 設置先項,不顯示宏調用
         1024 設置選頂,顯示第一遍掃描列表
         2048 設置選項,不顯示第一遍掃描列表
         4096 設置選項目,顯示條件彙編僞指令
         8192 設置選項,不顯示條件彙編僞指令
         16384 設置選項,顯示MEND 僞指令
         32768 設置選項,不顯示MEND 僞
         默認情況下,-list 選項生成常規的列表文件,包括變量聲明,宏展開,條件彙編僞指令及MEND 僞指令,而且列表文件只是在第二遍掃描時給出,通過OPT 僞指令,可以在源程序中改變默認的選項。
         僞指令應用舉例如下:
         … ;代碼
         OPT 512 ;不顯示宏調用
         … ;代碼

         TTL 和SUBT
         TTL 和SUBT 爲插入標題僞指令。
         TTL 僞指令在列表文件的每一頁的開頭插入一個標題。該TTL 僞指令的作用在其後的每一頁,直到遇到新的TTL 僞指令。
         SUBT 僞指令在列表文件的每頁的開頭第一個子標題。該SUBT 僞指令的作用在其後的每一頁,直到遇到新的SUBT 僞指令。
         僞指令格式:
         TTL title
         SUBT subtitle
         其中:title 標題名。
         subtitle 子標題名。
         僞指令應用舉例如下:
         …
         TTL mainc
         …
         SUBT subc con
         …

A.4.3  彙編控制僞指令
         彙編控制僞指令用於條件彙編、宏定義、重複彙編控制等。該類僞指令如下:
         條件彙編控制: IF、ELSE 和ENDIF
         宏定義: MACRO 和MEND
         重複彙編: WHILE 及WEND

         IF、ELSE 和ENDIF
         IF 、ELSE 和ENDIF 僞指令能夠根據條件把一段代碼包括在彙編程序內或將其排除在程序之外。
         [與IF 同義,|與ELSE 同義,]與ENDIF 同義。
         僞指令格式:
         IF logical_expr
         ;指令或僞指令代碼段1
         ELSE
         ;指令或僞指令代碼段2
         ENDIF
         其中:logical_expr 用於控制的邏輯表達式。若條件成立,則代碼段落在彙編源程序中有效。若條件不成立,代碼段1 無效,同時若使用ELSE 僞指令,代碼段有效。
         僞指令應用舉例如下:
         …
         IF {CONFIG}=16
         BNE __rt_udiv_1
         LDR R0,=__rt_div0
         BX R0
         ELSE
         BEQ __rt_div0
         ENDIF
         IF、ELSE 和ENDIF 僞指令是可以嵌套使用的。

         MACRO 和MEND
         MACRO 和MEND 僞指令用於宏定義。MACRO 標識宏定義的開始,MEND 標識宏定義久的結束。用MACRO 及MEND 定義的一段代碼,稱爲宏定義體。這樣在程序中就可以通過宏指令多次調用該代碼段。
         僞指令格式:
         MACRO
         {$label} macroname {$parameter} {$parameter}…
         ;宏定義體。
         MEND
         其中:$label 宏指令被展開時,label 可被替換成相應的符號,通常爲一個標號在一個符號前使用$表示被彙編時將使用相應的值替代$後的符號。
         macroname 所定義的宏的名稱。
         $parameter 宏指令的參數。當宏指令被展開時將被替換成相應的值,類似於函數中的形式參數。
         對於子程序代碼比較短,而需要傳遞的參數比較多的情況下可以使用匯編技術。首先要用MACR 和MEND 僞指令定義宏,包括宏定義體代碼。在MACRO 僞指令之後的第一行聲明宏的原型,其中包含該宏定義的名稱,及需要的參數。在彙編程序中可以通過該宏定義的名稱來調用它。當源程序被彙編時,彙編編譯器將展開每個宏調用,用宏定義體代替源程序中的宏定義的名稱,並用實際的參數值代替宏定義時的形式參數。
         僞指令應用舉例如下:
         MACRO
         CSI_SETB ;宏名爲CSI_SETB,無參數
         LDR R0,=rPDATG ;讀取GPG0 口的值
         LDR R1,[R0]
         ORR R1,R1#0x01 ;CSI 置位操作
         STR R1,[R0] ;輸出控制
         MEND
         帶參數的宏定義如程序清單:
         MACRO
         $IRQ_Label HANDLER $IRQ_Exception
         EXPORT $IRQ_Label
         IMPORT $IRQ_Exception
         $IRQ_Label
         SUB LR,LR,#4
         STMFD SP!,{R0-R3,R12,LR}
         MRS R3,STSR
         STMFD SP!,{R3}
         …
         MEND

         WHIL 和WEND
         WHILE 和WEND 僞指令用於根據條件重複彙編相同的或幾乎相同的一段源程序。
         僞指令格式:
         WHILE logical_expr
         ;指令或僞指令代碼段
         WEND
         其中:logical_expr 用於控制的邏輯表達式。若條件成立,則代碼段在彙編源程序中有效,並不斷重複這段代碼直到條件不成立。
         僞指令應用舉例如下:
         WHILE no<5
         no SETA no+1
         …
         WEND
         WHILE 和WEND 僞指令是可以嵌套使用的。

A.4.5  雜項僞指令
         雜項僞指令在彙編編程設計較爲常用,如段定義僞指令,入口點設置僞指令,包含文件僞指令,標號導出或引入聲明等,該類僞指令如下:
         邊界對齊: ALIGN。
         段定義: AREA。
         指令集定義: CODE16 和CODE32。
         彙編結束: END。
         程序入口: ENTRY。
         常量定義: EQU。
         聲明一個符號可以被其它文件引用:EXPORT 和GLORBAL。
         聲明一個外部符號:IMPORT 和EXTERN。
         包含文件:GET 和INCLUDE。
         包含不被彙編的文件:INCBIN。
         保留符號表中的局部符號:KEEP。
         禁止浮點指令:NOFP。
         指示兩段之間的依賴關係:REQUIRE。
         堆棧8 字節對準:PEQUIRE8 和PRESERVE8。
         給特定的寄存器命名:RN。
         標記局部標號使用範圍的界限:ROUT。

         ALIGN
         ALIGN 僞指令通過添加補丁字節使當前位置滿足一定的對齊方式。
         僞指令格式:
         ALIGN {expr{,offset}}
         其中:expr 數字表達式,用於指定對齊的方式。取值爲2 的n 次冪,如1、2、4、8等,不能爲0 其沒有expr,則默認爲字對齊方式。
         offset 數字表達式,當前位置對齊到下面形式的地址處:offset+n*expr
         在下面的情況中,需要特定的地址對齊方式:
         (A)Thumb 僞指令ADR 要求地址是字對齊的。而Thumb 代碼中地址標號可能不是字對齊的。這時就要使用僞指令ALIGN4 使Thumb 代碼中地址標號爲字對齊。
         (B)由於有些ARM 處理器的Cache 採用了其他對齊方式。如16 字節對齊方式,這時使用ALIGN 僞指令指定合適的對齊方式可以充分發揮Cache 的性能優勢。
         (C)LDRD 和STRD 指令要求存儲單元爲8 字節對齊。這樣在爲LDRD/STRD 指令分配的存儲單元前要使用僞指令ALIGN8 實現8 字節對齊方式。
         (D)地址標號通常自身沒有對齊要求,而在ARM 代碼中要求地起標號對齊是字對齊的,Thumb 代碼中要求半字對齊。這樣可以使用ALIGN4 和ALIGN2 僞指令來調整對齊方式。
         僞指令應用舉例如下。
         通過ALIGN 僞指令使程序中的地址標號字對齊:
         AREA Example,CODE,READONLY ;聲明代碼段Example
         START LDR R0,=Sdfjk
         …
         MOV PC,LR
         Sdfjk DCB 0x58 ;定義一字節存儲空間,字對齊方式被破壞
         ALIGN ;聲明字對齊
         SUBI MOV R1,R3 ;其它代碼
         …
         MOV PC,LR
         在段定義AREA 中,也可使用ALIGN 僞指令對齊,但表達式的數字含義是同的
         AREA MyStack,DATA,NOINIT,ALIGN=2 ;聲明數據段
         ;MyStack,並重新字對齊
         IrqStackSpace SPACE IRQ_STACK_LEGTH*4 ;中斷模式堆棧空間
         FiqStackSpace SPACE FIQ_STACK_LEGTH*4 ;快速中斷模式堆棧空間
         AbtStackSpace SPACE ABT_STACK_LEGTH*4 ;中止義模式堆棧空間
         UndtStackSpace SPACE UND_STACK_LEGTH*4 ;未定義模式堆棧
         …
         將兩個字節的數據放在同一個字的第一個字節和第四個字節中,帶offset 的ALIGN對齊:
         AREA offsetFxample, CODE
         DCB 0x31 ;第一個字節保存0x31
         ALIGN 4,3 ;字對齊
         DCB 0x32 ;第四個字節保存0x32
         …

         AREA
         AREA 僞指令用於定義一個代碼段或數據段。ARM 彙編程序設計採用分段式設計,一個ARM 源程序至少需要一個代碼段,大的程序可以包含多少個代碼段及數據段。
         僞指令格式:
         AREA sectionname{,attr}{,attr}…
         其中:sectionname 所定義的代碼段或數據段的名稱。如果該名稱是以數據開頭的,則該名稱必須用“|”括起來,如|1_datasec|。還有一些代碼段具有的約定的名稱。如|text|表示C 語言編譯器產生的代碼段或者與C 語言庫相關的代碼段。
         attr 該代碼段或數據段的屬性。
         在AREA 僞指令中,各屬性之間用逗號隔開。以下爲段屬性及相關說明:
         ALIGN = expr。默認的情況下,ELF 的代碼段和數據段是4 字節對齊的,expr 可以取0~31 的數值,相應的對齊方爲2expr 字節對齊。如expr=3 時爲字節對齊。對於代碼段,expr 不能爲0 或1。
         ASSOC = section。指定與本段相關的ELF 段。任何時候連接section 段也必須包括sectionname 段。
         DODE 爲定義代碼段。默認屬性爲READONLY。
         COMDEF 定義一個通用的段。該段可以包含代碼或者數據。在其它源文件中,同名的COMDEF 段必須相同。
         COMMON 定義一個通用的段。該段不包含任何用戶代碼和數據,連接器將其初始化爲此。各源文件中同名的COMMON 段共用同樣的內存單元,連接器爲其分配合適的尺寸。
         DATA 爲定義段。默認屬性爲READWRITE。
         NOINIT 指定本數據段僅僅保留了內存單元,而沒有將各初始寫入內存單元,或者將內存單元值初始化爲0。
         READONLY 指定本段爲只讀,代碼段的默認屬性爲READONLY。
         READWRITE 指定本段爲可讀可寫。數據段的默認屬性爲READWRITE。
         使用AREA 僞指令將程序分爲多個ELF 格式的段,段名稱可以相同, 這時同名的段被放在同一個ELF 段中。
         僞指令應用舉例如下:
         AREA Example ,CODE,READNOLY ;聲明一個代碼,名爲Example

         CODE16 和CODE32
         CODE16 僞指令指示彙編編譯器後面的指令爲16 位的Thumb 指令。
         CODE32 僞指令指示彙編編譯器後面的指令爲32 位的ARM 指令。
         僞指令格式:
         CODE16
         CODE32
         CODE16 和CODE32 僞指令只是指示彙編編譯器後面的指令的類型,僞指令本身並不進行程序狀態的切換。要進行狀態切換,可以使用BX 指令操作。
         僞指令應用舉例如下:
         AREA Example CODE,READONLY
         CODE32
         …
         使用CODE16 和CODE32 定義Thumb 指令及ARM 指令並用BX 指令進行切換。
         CODE16 和CODE32 的使用:
         AREA ArmThumC,CODE,READONLY
         CODE32
         ADR R0,ThumbStart+1
         BX R0
         CODE16
         ThumbStart
         MOV R0,#10
         …
         END

         END
         END 僞指令用於指示彙編編譯器源文件已結束。每一個彙編源文件均要使用一個END 僞指令,指示本源程序結束。
         僞指令格式:
         END

         ENTRY
         ENTRY 僞指令用於指定程序的入口點。
         僞指令格式:
         ENTRY
         一個程序(可以包含多個源文件)中至少要有一個ENTRY,可以有多個ENTRY。但一個源文件中最多隻有一個ENTRY。
         僞指令應用舉例如下。
         AREA, Example, CODE,READNOLY
         ENTRY
         CODE32
         START MOV R1,#0x5F
         …

         EQU
         EQU 僞指令爲數字常量,基於寄存器的值和程序中的標號定義一個名稱。*與EQU同義。
         指令格式:
         name EQU expr{,type}
         其中:name 要定義的常量的名稱。
         expr 基於寄存器的地址值,程序中的標號,32 位地址常量或32 位常量。
         type 當expr 爲32 位常量時,可用type 指示expr 表示的數據類型。如下示例:
         CODE16
         CODE32
         DATA
         EQU 僞指令的作用類似於C 語言中的#define。用於爲一個常量定義名稱。
         僞指令應用舉例如下:
         T_bit EQU 0x20 ;定義常量T_bit,其值爲0x20
         PLLCON EQU 0xE01FC080 ;定義寄存器PLLCON,地址爲0Xe01F080
         ABCD EQU label+8 ;定義ABCD 爲label+8

         EXPORT 和GLOBAL
         EXPORT 聲明一個符號可以被其它文件引用。相當於聲明瞭一個全局變量。
         GLOBAL 與EXPORT 相同
         指令格式:
         EXPORT symbol{[WEAK]}
         GLOBAL symbol{[WEAK]}
         其中:symbol 要聲明的符號名稱
         [WEAK] 聲明其它的同名符優先於本符號被引用。
         僞指令應用舉例如下:
         EXPORT InitStack
         GLOBAL Vectors

         IMPORT 和EXTERN
         IMJPORT 僞指令指示編譯器當前的符號不是在本源文件中定義的,而是在其他源文件中定義的,在本源文件中可能引用該符號。
         EXTERN 與IMPORT 相同
         指令格式:
         IMPORT symbol{[WEAK]}
         EXTERN symbol{[WEAK]}
         其中:symbol 要聲明的符號名稱。
         [WEAK] 指定該選項後,如果symbol 在所有的源程序中都沒有被定義,編譯器也不會生任何錯誤信息,同時編譯器也不會到當前沒有被INCLUDE 進來庫中去查找該標號。
         使用IMPORT 或EXTERN 聲明外部標號時,若連接器在連接處理時不能解釋該符號,而僞指令中沒有[WEAK]選項,則連接器會報告錯誤,若僞指令中有[WEAK]選項,則連接器不會報告錯誤,而是進行下面的操作:
         (A)如果該符號被B 或者BL 指令引用,則該符號被設置成下一條指令的地址,該B 或者BL 指令相當於一條NOP 指令。
         (B)其它情況下該符號被設置0。
         僞指令應用舉例如下:
         IMPORT InitStack
         EXTERN Vectors

         GET 和INCLUDE
         GET 僞指令將一個源文件包含到當前源文件中,並將被包含的文件在當前位置進行彙編處理。INCLUDE 與GFT 同義。
         指令格式:
         GET filename
         INCLUDE filename
         其中:filename 要包含的源文件名,可以使用路徑信息。
         GET 僞指令通常用於包含一些宏定義或常量定義的源文件。如用EQU 定義的常量,用MAP 和FIELD 定義的結構化的數據類型,這樣的源文件類似於C 語言中的頭文件,GET、INCLUDE 僞指令不能用來包含目標文件,而INCBIN 僞指令可以包含目標文件。
         僞指令應用舉例如下:
         INCLUDE LPC2106.inc

         INCBIN
         INCBIN 僞指令將一個文件包含到當前源文件中,而被包含的文件不進行彙編處理。
         指令格式:
         INCBIN filename
         其中:filename 要包含的源文件名,可以使用路徑信息。
         通常可以使用INCBIN 將一個執行文件或者任意數據包含到當前文件中,被包含的執行文件或數據將被原封不動地放下當前文件中,編譯器從INCBIN 僞指令後面開始繼續處理。
         僞指令應用舉例如下:
         NCBIN charlib。bin

         KEEP
         KEEP 僞指令指示編譯器保留符號表中的局部符號。
         僞指令格式:
         KEEP {symbol}
         其中:symbol 要保留的局部標號。若沒有此項,則除了基於寄存器處的所有符號將包含在目標文件的符號表中。

         NOFP
         NOFP 僞指令用於禁止源程序中包含浮點運算指令。
         僞指令格式:
         NOFP

         REQUIRE
         REQUIRE 僞指令指定段之間的依賴關係。
         僞指令格式:
         REQUIRE label
         其中:label 所需要的標號的名稱。
         當進行鏈接處理時,包含了REQUIRE label 僞指令的源文件,則定義label 的源文件也被包含。

         PEQUIRE8 和PRESERVE8
         PEQUIRE8 僞指令指示當前文件請求堆棧爲8 字節對齊。
         PRESERVE8 僞指令指示當前文件保持堆棧爲8 字節對齊。
         僞指令格式:
         PEQUIRE8
         PRESERVE8
         鏈接器保證要求8 字節對齊的堆棧只能被堆棧爲8 字的對齊的代碼調用

http://blog.chinaunix.net/u3/104319/showart_2075003.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章