新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM程序設計基礎

        ARM程序設計基礎

        作者: 時間:2016-11-22 來源:網絡 收藏

        RSB{條件}{S} 目的寄存器,操作數1,操作數2

        RSB指令稱為逆向減法指令,用于把操作數2減去操作數1,并將結果存放到目的寄存器中。

        RSC{條件}{S} 目的寄存器,操作數1,操作數2

        RSC指令用于把操作數2減去操作數1,再減去CPSR中的C條件標志位的反碼,并將結果存放到目的寄存器中。

        AND{條件}{S} 目的寄存器,操作數1,操作數2

        OR{條件}{S} 目的寄存器,操作數1,操作數2

        EOR{條件}{S} 目的寄存器,操作數1,操作數2

        EOR指令用于在兩個操作數上進行邏輯異或運算,并把結果放置到目的寄存器中。

        BIC{條件}{S} 目的寄存器,操作數1,操作數2

        BIC指令用于清除操作數1的某些位,并把結果放置到目的寄存器中。

        nMUL 32位乘法指令

        nMLA 32位乘加指令

        nSMULL 64位有符號數乘法指令

        nSMLAL 64位有符號數乘加指令

        nUMULL 64位無符號數乘法指令

        nUMLAL 64位無符號數乘加指令

        ASR n 算術右移n位(1<=n<=32)

        LSL n 邏輯左移n位(1<=n<=32)

        LSR n 邏輯右移n位(1<=n<=32)

        ROR n 循環右移n位(1<=n<=32)

        RRX 帶擴展的循環右移1位

        3程序狀態寄存器處理指令

        ARM微處理器支持程序狀態寄存器訪問指令,用于在程序狀態寄存器和通用寄存器之間傳送數據。

        nMRS 程序狀態寄存器到通用寄存器的數據傳送指令

        nMSR 通用寄存器到程序狀態寄存器的數據傳送指令

        4程序狀態寄存器處理指令

        加載指令用于將存儲器中的數據傳送到寄存器,存儲指令則完成相反的操作。

        nLDR 字數據加載指令

        nLDRB 字節數據加載指令

        nLDRH 半字數據加載指令

        nSTR 字數據存儲指令

        nSTRB 字節數據存儲指令

        nSTRH 半字數據存儲指令

        nLDM 批量數據加載指令

        nSTM 批量數據存儲指令

        4批量數據加載/存儲指令

        ARM微處理器所支持批量數據加載/存儲指令可以一次在一片連續的存儲器單元和多個寄存器之間傳送數據,批量加載指令用于將一片連續的存儲器中的數據傳送到多個寄存器,批量數據存儲指令則完成相反的操作。

        nLDM 批量數據加載指令

        nSTM 批量數據存儲指令

        ARM微處理器所支持的數據交換指令能在存儲器和寄存器之間交換數據。

        nSWP 字數據交換指令

        nSWPB 字節數據交換指令

        5協處理器指令

        nCDP 協處理器數操作指令

        nLDC 協處理器數據加載指令

        nSTC 協處理器數據存儲指令

        nMCR 寄存器到協處理器寄存器的數據傳送指令

        nMRC 協處理器寄存器到寄存器的數據傳送指令

        異常產生指令

        nSWI 軟件中斷指令

        nBKPT 斷點中斷指令

        3匯編語言的語句格式

        ARM(Thumb)匯編語言的語句格式為:

        {標號} {指令或偽指令} {;注釋}

        在匯編語言程序設計中,每一條指令的助記符可以全部用大寫、或全部用小寫,但不用許在一條指令中大、小寫混用。

        同時,如果一條語句太長,可將該長語句分為若干行來書寫,在行的末尾用“”表示下一行與本行為同一條語句。

        3.1 在匯編語言程序中常用的符號

        在匯編語言程序設計中,經常使用各種符號代替地址、變量和常量等,以增加程序的可讀性。盡管符號的命名由編程者決定,但并不是任意的,必須遵循以下的約定:

        — 符號區分大小寫,同名的大、小寫符號會被編譯器認為是兩個不同的符號。

        — 符號在其作用范圍內必須唯一。

        — 自定義的符號名不能與系統的保留字相同。

        — 符號名不應與指令或偽指令同名。

        1、 程序中的變量

        程序中的變量是指其值在程序的運行過程中可以改變的量。ARM(Thumb)匯編程序所支持的變量有數字變量、邏輯變量和字符串變量。

        數字變量用于在程序的運行中保存數字值,但注意數字值的大小不應超出數字變量所能表示的范圍。

        邏輯變量用于在程序的運行中保存邏輯值,邏輯值只有兩種取值情況:真或假。

        字符串變量用于在程序的運行中保存一個字符串,但注意字符串的長度不應超出字符串變量所能表示的范圍。

        在ARM(Thumb)匯編語言程序設計中,可使用GBLA、GBLL、GBLS偽指令聲明全局變量,使用LCLA、LCLL、LCLS偽指令聲明局部變量,并可使用SETA、SETL和SETS對其進行初始化。

        2、 程序中的常量

        程序中的常量是指其值在程序的運行過程中不能被改變的量。ARM(Thumb)匯編程序所支持的常量有數字常量、邏輯常量和字符串常量。

        數字常量一般為32位的整數,當作為無符號數時,其取值范圍為0~232-1,當作為有符號數時,其取值范圍為-231~231-1。

        邏輯常量只有兩種取值情況:真或假。

        字符串常量為一個固定的字符串,一般用于程序運行時的信息提示。

        3、 程序中的變量代換

        程序中的變量可通過代換操作取得一個常量。代換操作符為“$”。

        如果在數字變量前面有一個代換操作符“$”,編譯器會將該數字變量的值轉換為十六進制的字符串,并將該十六進制的字符串代換“$”后的數字變量。

        如果在邏輯變量前面有一個代換操作符“$”,編譯器會將該邏輯變量代換為它的取值(真或假)。

        如果在字符串變量前面有一個代換操作符“$”,編譯器會將該字符串變量的值代換“$”后的字符串變量。

        使用示例:

        LCLS S1 ;定義局部字符串變量S1和S2

        LCLS S2

        S1 SETS “Test!”

        S2 SETS “This is a $S1” ;字符串變量S2的值為“This is a Test!”

        3.2 匯編語言程序中的表達式和運算符

        在匯編語言程序設計中,也經常使用各種表達式,表達式一般由變量、常量、運算符和括號構成。常用的表達式有數字表達式、邏輯表達式和字符串表達式,其運算次序遵循如下的優先級:

        — 優先級相同的雙目運算符的運算順序為從左到右。

        — 相鄰的單目運算符的運算順序為從右到左,且單目運算符的優先級高于其他運算符。

        — 括號運算符的優先級最高。

        1、 數字表達式及運算符

        數字表達式一般由數字常量、數字變量、數字運算符和括號構成。與數字表達式相關的運算符如下:

        — “+”、“-”、“×”、“/” 及“MOD”算術運算符

        以上的算術運算符分別代表加、減、乘、除和取余數運算。例如,以X和Y表示兩個數字表達式,則:

        X+Y 表示X與Y的和。

        X-Y 表示X與Y的差。

        X×Y 表示X與Y的乘積。

        X/Y 表示X除以Y的商。

        X:MOD:Y 表示X除以Y的余數。

        — “ROL”、“ROR”、“SHL”及“SHR”移位運算符

        以X和Y表示兩個數字表達式,以上的移位運算符代表的運算如下:

        X:ROL:Y 表示將X循環左移Y位。

        X:ROR:Y 表示將X循環右移Y位。

        X:SHL:Y 表示將X左移Y位。

        X:SHR:Y 表示將X右移Y位。

        — “AND”、“OR”、“NOT”及“EOR”按位邏輯運算符

        以X和Y表示兩個數字表達式,以上的按位邏輯運算符代表的運算如下:

        X:AND:Y 表示將X和Y按位作邏輯與的操作。

        X:OR:Y 表示將X和Y按位作邏輯或的操作。

        :NOT:Y 表示將Y按位作邏輯非的操作。

        X:EOR:Y 表示將X和Y按位作邏輯異或的操作。

        2、 邏輯表達式及運算符

        邏輯表達式一般由邏輯量、邏輯運算符和括號構成,其表達式的運算結果為真或假。與邏輯表達式相關的運算符如下:

        — “=”、“>”、“<”、“>=”、“<= ”、“/=”、“ <>” 運算符

        以X和Y表示兩個邏輯表達式,以上的運算符代表的運算如下:

        X = Y 表示X等于Y。

        X > Y 表示X大于Y。

        X < Y 表示X小于Y。

        X >= Y 表示X大于等于Y。

        X <= Y 表示X小于等于Y。

        X /= Y 表示X不等于Y。

        X <> Y 表示X不等于Y。

        — “LAND”、“LOR”、“LNOT”及“LEOR”運算符

        以X和Y表示兩個邏輯表達式,以上的邏輯運算符代表的運算如下:

        X:LAND:Y 表示將X和Y 作邏輯與的操作。

        X:LOR:Y 表示將X和Y作邏輯或的操作。

        :LNOT:Y 表示將Y作邏輯非的操作。

        X:LEOR:Y 表示將X和Y作邏輯異或的操作。

        3、 字符串表達式及運算符

        字符串表達式一般由字符串常量、字符串變量、運算符和括號構成。編譯器所支持的字符串最大長度為512字節。常用的與字符串表達式相關的運算符如下:

        — LEN運算符

        LEN運算符返回字符串的長度(字符數),以X表示字符串表達式,其語法格式如下:

        :LEN:X

        — CHR運算符

        CHR運算符將0~255之間的整數轉換為一個字符,以M表示某一個整數,其語法格式如下:

        :CHR:M

        — STR運算符

        STR運算符將將一個數字表達式或邏輯表達式轉換為一個字符串。對于數字表達式,STR運算符將其轉換為一個以十六進制組成的字符串;對于邏輯表達式,STR運算符將其轉換為字符串T或F,其語法格式如下:

        :STR:X

        其中,X為一個數字表達式或邏輯表達式。

        — LEFT運算符

        LEFT運算符返回某個字符串左端的一個子串,其語法格式如下:

        X:LEFT:Y

        其中:X為源字符串,Y為一個整數,表示要返回的字符個數。

        — RIGHT運算符

        與LEFT運算符相對應,RIGHT運算符返回某個字符串右端的一個子串,其語法格式如下:

        X:RIGHT:Y

        其中:X為源字符串,Y為一個整數,表示要返回的字符個數。

        — CC運算符

        CC運算符用于將兩個字符串連接成一個字符串,其語法格式如下:

        X:CC:Y

        其中:X為源字符串1,Y為源字符串2,CC運算符將Y連接到X的后面。

        4、 與寄存器和程序計數器(PC)相關的表達式及運算符

        常用的與寄存器和程序計數器(PC)相關的表達式及運算符如下:

        — BASE運算符

        BASE運算符返回基于寄存器的表達式中寄存器的編號,其語法格式如下:

        :BASE:X

        其中,X為與寄存器相關的表達式。

        — INDEX運算符

        INDEX運算符返回基于寄存器的表達式中相對于其基址寄存器的偏移量,其語法格式如下:

        :INDEX:X

        其中,X為與寄存器相關的表達式。

        5、 其他常用運算符

        — ?運算符

        ?運算符返回某代碼行所生成的可執行代碼的長度,例如:

        ?X

        返回定義符號X的代碼行所生成的可執行代碼的字節數。

        — DEF運算符

        DEF運算符判斷是否定義某個符號,例如:

        :DEF:X

        如果符號X已經定義,則結果為真,否則為假。

        4匯編語言的程序結構

        4.1 匯編語言的程序結構

        在ARM(Thumb)匯編語言程序中,以程序段為單位組織代碼。段是相對獨立的指令或數據序列,具有特定的名稱。段可以分為代碼段和數據段,代碼段的內容為執行代碼,數據段存放代碼運行時需要用到的數據。一個匯編程序至少應該有一個代碼段,當程序較長時,可以分割為多個代碼段和數據段,多個段在程序編譯鏈接時最終形成一個可執行的映象文件。

        可執行映象文件通常由以下幾部分構成:

        — 一個或多個代碼段,代碼段的屬性為只讀。

        — 零個或多個包含初始化數據的數據段,數據段的屬性為可讀寫。

        — 零個或多個不包含初始化數據的數據段,數據段的屬性為可讀寫。

        鏈接器根據系統默認或用戶設定的規則,將各個段安排在存儲器中的相應位置。因此源程序中段之間的相對位置與可執行的映象文件中段的相對位置一般不會相同。

        以下是一個匯編語言源程序的基本結構:

        AREA Init,CODE,READONLY

        ENTRY

        Start

        LDR R0,=0x3FF5000

        LDR R1,0xFF

        STR R1,[R0]

        LDR R0,=0x3FF5008

        LDR R1,0x01

        STR R1,[R0]

        ┉┉

        END

        在匯編語言程序中,用AREA偽指令定義一個段,并說明所定義段的相關屬性,本例定義一個名為Init的代碼段,屬性為只讀。ENTRY偽指令標識程序的入口點,接下來為指令序列,程序的末尾為END偽指令,該偽指令告訴編譯器源文件的結束,每一個匯編程序段都必須有一條END偽指令,指示代碼段的結束。

        4.2 匯編語言的子程序調用

        在ARM匯編語言程序中,子程序的調用一般是通過BL指令來實現的。在程序中,使用指令:BL 子程序名

        即可完成子程序的調用。

        該指令在執行時完成如下操作:將子程序的返回地址存放在連接寄存器LR中,同時將程序計數器PC指向子程序的入口點,當子程序執行完畢需要返回調用處時,只需要將存放在LR中的返回地址重新拷貝給程序計數器PC即可。在調用子程序的同時,也可以完成參數的傳遞和從子程序返回運算的結果,通常可以使用寄存器R0~R3完成。

        以下是使用BL指令調用子程序的匯編語言源程序的基本結構:

        AREA Init,CODE,READONLY

        ENTRY

        Start

        LDR R0,=0x3FF5000

        LDR R1,0xFF

        STR R1,[R0]

        LDR R0,=0x3FF5008

        LDR R1,0x01

        STR R1,[R0]

        BL PRINT_TEXT

        ┉┉

        PRINT_TEXT

        ┉┉

        MOV PC,BL

        ┉┉

        END

        4.3 匯編語言程序示例

        以下是一個基于S3C4510B的串行通訊程序,關于S3C4510B的串行通訊的工作原理,可以參考第六章的相關內容,在此僅向讀者說明一個完整匯編語言程序的基本結構:

        ;********************************************************************************

        ; Instituteof Automation,Chinese Academyof Sciences

        ;Description: This example shows the UART communication!

        ;Author: JuGuang,Lee

        ;Date:

        ;********************************************************************************

        UARTLCON0 EQU 0x3FFD000

        UARTCONT0 EQU 0x3FFD004

        UARTSTAT0 EQU 0x3FFD008

        UTXBUF0 EQU 0x3FFD00C

        UARTBRD0 EQU 0x3FFD014

        AREAInit,CODE,READONLY

        ENTRY

        ;**************************************************

        ;LED Display

        ;**************************************************

        LDR R1,=0x3FF5000

        LDR R0,=&ff

        STR R0,[R1]

        LDR R1,=0x3FF5008

        LDR R0,=&ff

        STR R0,[R1]

        ;*************************************************

        ;UART0 line controlregister

        ;*************************************************

        LDR R1,=UARTLCON0

        LDR R0,=0x03

        STR R0,[R1]

        ;**************************************************

        ;UART0 control regiser

        ;**************************************************

        LDR R1,=UARTCONT0

        LDR R0,=0x9

        STR R0,[R1]

        ;**************************************************

        ;UART0 baud rate divisorregiser

        ;Baudrate=19200,對應于50MHz的系統工作頻率

        ;***************************************************

        LDR R1,=UARTBRD0

        LDR R0,=0x500

        STR R0,[R1]

        ;***************************************************

        ;Print the messages!

        ;***************************************************

        LOOP

        LDR R0,=Line1

        BL PrintLine

        LDR R0,=Line2

        BL PrintLine

        LDR R0,=Line3

        BL PrintLine

        LDR R0,=Line4

        BL PrintLine

        LDR R1,=0x7FFFFF

        LOOP1

        SUBS R1,R1,#1

        BNE LOOP1

        B LOOP

        ;***************************************************

        ;Print line

        ;***************************************************

        PrintLine

        MOV R4,LR

        MOV R5,R0

        Line

        LDRB R1,[R5],#1

        AND R0,R1,#&FF

        TST R0,#&FF

        MOVEQ PC,R4

        BL PutByte

        B Line

        PutByte

        LDR R3,=UARTSTAT0

        LDR R2,[R3]

        TST R2,#&40

        BEQ PutByte

        LDR R3,=UTXBUF0

        STR R0,[R3]

        MOV PC,LR

        Line1 DCB &A,&D,"******************************************************************",0

        Line2 DCB &A,&D,"ChineseAcademy of Sciences,Institute of Automation,Complex System Lab.",0

        Line3 DCB &A,&D," ARM Development Board Based on SamsungARM S3C4510B.",0

        Line4 DCB &A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,&A,&D,0

        END

        4.4 匯編語言與C/C++的混合編程

        在應用系統的程序設計中,若所有的編程任務均用匯編語言來完成,其工作量是可想而知的,同時,不利于系統升級或應用軟件移植,事實上,ARM體系結構支持C/C+以及與匯編語言的混合編程,在一個完整的程序設計的中,除了初始化部分用匯編語言完成以外,其主要的編程任務一般都用C/C++ 完成。

        匯編語言與C/C++的混合編程通常有以下幾種方式:

        - 在C/C++代碼中嵌入匯編指令。

        - 在匯編程序和C/C++的程序之間進行變量的互訪。

        - 匯編程序、C/C++程序間的相互調用。

        在以上的幾種混合編程技術中,必須遵守一定的調用規則,如物理寄存器的使用、參數的傳遞等,這對于初學者來說,無疑顯得過于煩瑣。在實際的編程應用中,使用較多的方式是:程序的初始化部分用匯編語言完成,然后用C/C++完成主要的編程任務,程序在執行時首先完成初始化過程,然后跳轉到C/C++程序代碼中,匯編程序和C/C++程序之間一般沒有參數的傳遞,也沒有頻繁的相互調用,因此,整個程序的結構顯得相對簡單,容易理解。以下是一個這種結構程序的基本示例,該程序基于第五、六章所描述的硬件平臺:

        ;*************************************************************************

        ; Instituteof Automation, Chinese Academyof Sciences

        ;File Name: Init.s

        ;Description:

        ;Author: JuGuang,Lee

        ;Date:

        ;************************************************************************

        IMPORTMain ;通知編譯器該標號為一個外部標號

        AREA Init,CODE,READONLY ;定義一個代碼段

        ENTRY ;定義程序的入口點

        LDR R0,=0x3FF0000 ;初始化系統配置寄存器,具體內容可參考第五、六章

        LDR R1,=0xE7FFFF80

        STR R1,[R0]

        LDR SP,=0x3FE1000 ;初始化用戶堆棧,具體內容可參考第五、六章

        BL Main ;跳轉到Main()函數處的C/C++代碼執行

        END ;標識匯編程序的結束

        以上的程序段完成一些簡單的初始化,然后跳轉到Main()函數所標識的C/C++代碼處執行主要的任務,此處的Main僅為一個標號,也可使用其他名稱,與C語言程序中的main()函數沒有關系。

        /*******************************************************************************

        * Instituteof Automation, Chinese Academyof Sciences

        * File Name: main.c

        * Description: P0,P1LED flash.

        * Author: JuGuang,Lee

        * Date:

        ******************************************************************************/

        void Main(void)

        {

        inti;

        *((volatile unsigned long *) 0x3ff5000) = 0x0000000f;

        while(1)

        {

        *((volatile unsignedlong *) 0x3ff5008) = 0x00000001;

        for(i=0;i<0x7fFFF; i++);

        *((volatileunsigned long *) 0x3ff5008) = 0x00000002;

        for(i=0;i<0x7FFFF; i++);

        }

        }


        上一頁 1 2 下一頁

        關鍵詞: ARM程序設計基

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 福海县| 九台市| 红安县| 元阳县| 吉林市| 皮山县| 诸暨市| 辉县市| 车致| 手游| 古交市| 吉安县| 洛浦县| 凉山| 江油市| 肥乡县| 正阳县| 义马市| 宝丰县| 平乐县| 齐河县| 雷波县| 鄄城县| 博客| 千阳县| 会东县| 公主岭市| 土默特右旗| 屏边| 石楼县| 公安县| 柯坪县| 柳河县| 内丘县| 芦山县| 祥云县| 新郑市| 烟台市| 全州县| 酒泉市| 新乐市|