新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM學習手札之匯編偽指令

        ARM學習手札之匯編偽指令

        作者: 時間:2016-11-22 來源:網絡 收藏
        ARM 匯編程序由機器指令,偽指令和宏指令組成。偽指令不像機器指令那樣在處理器運行期間由機器執行,而是匯編程序對源程序匯編期間由匯編程序處理。在前面的指令集章節中,我們已經接觸了幾條常用到的偽指令,如ADR 、ADRL、LDR、NOP 等,把它們和指令集一起介紹是因為它們在匯編時會被合適的機器指令代替,實現真正機器指令操作。宏是一段獨立的程序代碼,它是通過偽指令定義的,在程序中使用宏指令即可調用宏。

        當程序被匯編時,匯編程序將對每個調用進行展開,用宏定義取代源程序中的宏指令。

        本文引用地址:http://www.104case.com/article/201611/319695.htm

        符號定義偽指令
        符號定義偽指令用于定義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 字的對齊的代碼調用



        關鍵詞: ARM匯編偽指

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 闵行区| 双峰县| 和硕县| 大关县| 永吉县| 竹溪县| 玛沁县| 庆城县| 裕民县| 陇川县| 江油市| 浦城县| 铁岭县| 灵台县| 获嘉县| 衡水市| 衡阳市| 都兰县| 保康县| 唐海县| 灌阳县| 文成县| 天全县| 固阳县| 章丘市| 长宁县| 托克逊县| 繁峙县| 崇义县| 犍为县| 富民县| 清水县| 高陵县| 阿坝| 环江| 米林县| 高唐县| 南雄市| 绩溪县| 扎赉特旗| 深水埗区|