新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 嵌入式Linux+ARMARM體系結構與編程(ARM匯編指令)

        嵌入式Linux+ARMARM體系結構與編程(ARM匯編指令)

        作者: 時間:2016-11-09 來源:網絡 收藏
        自己的一些簡單的總結,也是最常用的ARM匯編指令,之后也會不斷的補充完善。

        1.匯編系統預定義的段名

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

        .text @代碼段
        .data @初始化數據段
        .bss @未初始化數據段
        需要注意的是,源程序中.bss段應該在.text之前。

        2.定義入口點
        編程序的缺省入口是 start標號,用戶也可以在連接腳本文件中用ENTRY標志指明其它入口點。

        .text

        .global _start

        _start:

        3 .word用法

        word expression就是在當前位置放一個word型的值,這個值就是expression
        舉例來說,

        _rWTCON:

        .word 0x15300000
        就是在當前地址,即_rWTCON處放一個值0x15300000

        4.equ賦值操作,相當于c語言的宏定義

        .equ MEM_CTRL_BASE, 0x48000000 //注意要加,號

        5. 邏輯指令

        AND―――――邏輯"與"操作指令

        指令格式:
        AND{cond}{S} Rd,Rn,operand2
        AND指令將操作數operand2 與Rn 的值按位邏輯"與",結果存放到目的寄存器Rd 中。若設置S,則根據運算結果影響N、Z位,在計算第二操作數時,更新C位,不影響V位(指令ORR、EOR、BIC 對標志位的影響同AND 指令)。
        指令示例:
        ANDS R1,R1,R2 ;R1=R1&R2,并根據運算的結果更新標志位
        AND R0,R0,#0x0F ;R0=R0&0x0F,取出R0最低4位數據。
        ORR―――――邏輯"或"操作指令
        指令格式:ORR{cond}{S} Rd,Rn,operand2 ORR指令將操作數operand2 與Rn 的值按位邏輯"或",結果存放到目的寄存器Rd 中。指令示例:
        ORRS R1,R1,R2 ;R1=R1|R2,并根據運算的結果更新標志位
        ORR R0,R0,#0x0F ;R0=R0|0x0F,將R0最低4位置1,其余位不變。
        BIC―――――位清除指令
        指令格式:
        BIC{cond}{S} Rd,Rn,operand2
        BIC指令將Rn 的值與操作數operand2 的反碼按位邏輯"與",結果存放到目的寄存器Rd 中。
        指令示例:BIC R0,R0,#0x0F ;將R0最低4位清零,其余位不變。
        CMP―――――比較指令
        指令格式:
        CMP{cond} Rn,operand2
        CMP指令用Rn的值減去操作數operand2 ,并將結果的狀態(Rn 與operand2比較是大、小、相等)反映在CPSR中,以便后面的指令根據條件標志決定程序的走向。CMP指令與SUBS指令完成的操作一樣,只是CMP指令只減,不存結果。
        指令示例:
        cmp R0,R1 ;比較R0,R1
        beq stop ;R0=R1跳到stop
        blt less ;R0
        Less:...
        Stop:...

        參考:

        http://blog.csdn.net/denlee/article/details/2501182

        嵌入式開發中,匯編程序常常用于非常關鍵的地方,比如系統啟動時的初始化,進出中斷時的環境保存、恢復,對性能要求非常苛刻的函數等。

        1、相對跳轉指令:b、bl
        不同之處在于:bl指令除了跳轉之外,還將返回地址(bl的下一條指令的地址)保存在lr寄存器中。
        跳轉范圍:當前指令的前后32M。
        它們是與位置無關的指令。
        示例:
        b fun1
        ......
        fun1:
        bl fun2
        ......
        fun2:
        ......


        2、數據傳送指令:mov,地址讀取偽指令:ldr
        mov指令可以把一個寄存器的值賦給另一個寄存器,或者把一個常數賦給寄存器。
        例:
        mov r1, r2
        mov r1, #4096
        mov指令傳送的常數必須能用立即數來表示。
        當不知道一個數能否用立即數來表示時,可以使用ldr命令來賦值。ldr是偽指令,它不是真實存在的指令,編譯器會把它擴展成真正的指令:如果該常數能用立即數來表示,則使用mov指令;否則編譯時將該常數保存在某個位置,使用內存讀取指令把它讀出來。
        例:
        ldr r1, =4097
        ldr本意為“大范圍的地址讀取偽指令”,以下是獲得代碼的絕對地址:
        例:
        ldr r1, =label
        label:
        ......


        3、內存訪問指令:ldr、str、ldm、stm
        ldr指令既可能是大范圍的地址讀取偽指令,也可能是內存訪問指令。當它的第二個參數前面有“ = ”時,表示偽指令,否則表示內存訪問指令。
        ldr指令是從內存中讀取數據到寄存器,str指令把寄存器的值存儲到內存中,它們操作的數據都是32位的。
        例:
        ldr r1, [r2, #4] // 將地址為r2+4的內存單元數據讀取到r1中
        ldr r1, [r2] // 將地址為r2的內存單元數據讀取到r1中
        ldr r1, [r2], #4 // 將地址為r2的內存單元數據讀取到r1中,然后r2=r2+4
        str r1, [r2, #4] // 將r1的數據保存到地址為r2+4的內存單元中
        str r1, [r2] // 將r1的數據保存到地址為r2的內存單元中
        str r1, [r2], #4 // 將r1的數據保存到地址為r2的內存單元中,然后r2=r2+4
        ldm和stm屬于批量內存訪問指令,只用一條指令就可以讀寫多個數據。格式為:
        ldm {cond} { ! } { ^ }
        stm {cond} { ! } { ^ }
        其中,{cond}表示指令的執行條件有:

        條件碼(cond)

        助記符

        含義

        cpsr中條件標志位

        0000

        eq

        相等

        Z = 1

        0001

        ne

        不相等

        Z = 0

        0010

        cs/hs

        無符號數大于/等于

        C = 1

        0011

        cc/lo

        無符號數小于

        C = 0

        0100

        mi

        負數

        N = 1

        0101

        pl

        非負數

        N = 0

        0110

        vs

        上溢出

        V = 1

        0111

        vc

        沒有上溢出

        V = 0

        1000

        hi

        無符號數大于

        C = 1或Z = 0

        1001

        ls

        無符號數小于等于

        C = 0或Z = 1

        1010

        ge

        帶符號數大于等于

        N = 1, V = 1或N = 0, V = 0

        1011

        lt

        帶符號數小于

        N = 1, V = 0或N = 0, V = 1

        1100

        gt

        帶符號數大于

        Z = 0且N = V

        1101

        le

        帶符號數小于/等于

        Z = 1或N! = V

        1110

        al

        無條件執行

        -

        1111

        nv

        從不執行

        -

        大多數ARM指令都可以條件執行,即根據cpsr寄存器中的條件標志位決定是否執行該指令:如果條件不滿足,該指令相當于一條nop指令。
        每條ARM指令包含4位的條件碼域,這表明可以定義16個執行條件。
        cpsr條件標志位N、Z、C、V分別表示Negative、Zero、Carry、oVerflow。

        表示地址變化模式,有4種方式:
        ia (Increment After) :事后遞增方式。
        ib (Increment Before) :事先遞增方式。
        da (Decrement After) :事后遞減方式。
        db (Decrement Before):事先遞減方式。
        中保存內存的地址,如果后面加上感嘆號,指令執行后,rn的值會更新,等于下一個內存單元的地址。
        表示寄存器列表,對于ldm指令,從所對應的內存塊中取出數據,寫入這些寄存器;對于stm指令,把這些寄存器的值寫入所對應的內存塊中。
        {^}有兩種含義:
        如果中有pc寄存器,它表示指令執行后,spsr寄存器的值將自動到cpsr寄存器中——這常用于從中斷處理函數中返回;
        如果中沒有pc寄存器,{^}表示操作的是用戶模式下的寄存器,而不是當前特權模式的寄存器。
        例:
        HandleIRQ: @中斷入口函數
        sub lr, lr, #4 @計算返回地址
        stmdb sp!, { r0 - r12, lr } @保存使用的寄存器
        @r0 - r12, lr被保存在sp表示的內存中
        @“!”使得指令執行后sp = sp - 14 * 4

        ldr lr, =int_return @設置調用IRQ_Handle函數后的返回地址
        ldr pc, =IRQ_Handle @調用中斷分發函數
        int_return:
        ldmia sp!, { r0 - r12, pc }^ @中斷返回,“^”表示將spsr的值到cpsr
        @于是從irq模式返回被中斷的工作模式
        @“!”使得指令執行后sp = sp + 14 * 4


        4、加減指令:add、sub
        例:
        add r1, r2, #1 // r1 = r2 + 1
        sub r1, r2, #1 // r1 = r2 - 1


        5、程序狀態寄存器的訪問指令:msr、mrs
        ARM處理器有一個程序狀態寄存器(cpsr),它用來控制處理器的工作模式、設置中斷的總開關。
        例:
        msr cpsr, r0 // r0到cpsr中
        mrs r0, cpsr // cpsr到r0中

        6、其他偽指令
        .extern : 定義一個外部符號(可以是變量也可以是函數)
        .text : 表示現在的語句都屬于代碼段
        .global : 將本文件中的某個程序標號定義為全局的


        ARM-THUMB子程序調用規則:ATPCS
        為了使C語言程序和匯編程序之間能夠互相調用,必須為子程序間的調用制定規則,在ARM處理器中,這個規則被稱為ATPCS:ARM程序和THUMB程序中子程序調用的規則。基本的ATPCS規則包括寄存器使用規則、數據棧使用規則、參數傳遞規則。

        1、寄存器使用規則
        子程序間通過寄存器r0 ~ r3來傳遞參數,這時可以使用它們的別名a1 ~ a4。被調用的子程序返回前無需恢復r0 ~ r3的內容。
        在子程序中,使用r4 ~ r11來保存局部變量,這時可以使用它們的別名v1 ~ v8。如果在子程序中使用了它們的某些寄存器,子程序進入時要保存這些寄存器的值,在返回前恢復它們;對于子程序中沒有使用到的寄存器,則不必進行這些操作。在THUMB程序中,通常只能使用寄存器r4 ~ r7來保存局部變量。
        寄存器r12用作子程序間scratch寄存器,別名為ip。
        寄存器r13用作數據棧指針,別名為sp。在子程序中寄存器r13不能用作其他用途。它的值在進入、退出子程序時必須相等。
        寄存器r14稱為連接寄存器,別名為lr。它用于保存子程序的返回地址。如果在子程序中保存了返回地址(比如將lr值保存到數據棧中),r14可以用作其他用途。
        寄存器r15是程序計數器,別名為pc。它不能用作其他用途。

        寄存器

        別名

        使用規則

        r15

        pc

        程序計數器

        r14

        lr

        連接寄存器

        r13

        sp

        數據棧指針

        r12

        ip

        子 程序內部調用的scratch寄存器

        r11

        v8

        ARM狀態局部變量寄存器8

        r10

        v7、s1

        ARM狀態局部變量寄存器7、在支持數據棧檢查的ATPCS中為數據棧限制指針

        r9

        v6、sb

        ARM狀態局部變量寄存器6、在支持RWPI的ATPCS中為靜態基址寄存器

        r8

        v5

        ARM狀態局部變量寄存器5

        r7

        v4、wr

        ARM狀態局部變量寄存器4、THUMB狀態工作寄存器

        r6

        v3

        ARM狀態局部變量寄存器3

        r5

        v2

        ARM狀態局部變量寄存器2

        r4

        v1

        ARM狀態局部變量寄存器1

        r3

        a4

        參數/結果/scratch寄存器4

        r2

        a3

        參數/結果/scratch寄存器3

        r1

        a2

        參數/結果/scratch寄存器2

        r0

        a1

        參數/結果/scratch寄存器1


        2、數據棧使用規則
        數據棧有兩個增長方向:向內存地址減小的方向增長時,稱為DESCENDING棧;向內存地址增加的方向增長時,稱為ASCENDING棧。
        所謂數據棧的增長就是移動棧指針。當棧指針指向棧頂元素(最后一個入棧的數據)時,稱為FULL棧;當棧指針指向棧頂元素(最后一個入棧的數據)相鄰的一個空的數據單元時,稱為EMPTY棧。
        則數據棧可以分為4種:
        FD:Full Descending 滿遞減
        ED:Empty Descending 空遞減
        FA :Full Ascending 滿遞增
        EA:Empty Ascending 空遞增
        ATPCS規定數據棧為FD類型,并且對數據棧的操作是8字節對齊的。使用stmdb / ldmia批量內存訪問指令來操作FD數據棧。
        使用stmdb命令往數據棧中保存內容時,先遞減sp指針,再保存數據,使用ldmia命令從數據棧中恢復數據時,先獲得數據,再遞增sp指針,sp指針總是指向棧頂元素,這剛好是FD棧的定義。

        3、參數傳遞規則
        一般地,當參數個數不超過4個時,使用r0 ~ r3這4個寄存器來傳遞參數;如果參數個數超過4個,剩余的參數通過數據棧來傳遞。
        對于一般的返回結果,通常使用r0 ~ r3來傳遞。
        例:
        假設CopyCode2SDRAM函數是用C語言實現的,它的數據原型如下:
        int CopyCode2SDRAM( unsigned char *buf, unsigned long start_addr, int size )
        在匯編代碼中,使用下面的代碼調用它,并判斷返回值:
        ldr r0, =0x30000000 @1. 目標地址 = 0x30000000,這是SDRAM的起始地址
        mov r1, #0 @2. 源地址 = 0
        mov r2, #16*1024 @3. 長度 = 16K
        bl CopyCode2SDRAM @調用C函數CopyCode2SDRAM
        cmp a0, #0 @判斷函數返回值



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 板桥市| 龙泉市| 长宁县| 百色市| 胶州市| 峨眉山市| 昌图县| 临清市| 恩平市| 宜宾县| 青神县| 商丘市| 晋江市| 含山县| 绩溪县| 星座| 延安市| 韶山市| 双峰县| 佳木斯市| 行唐县| 海南省| 和平区| 荆门市| 佛坪县| 山西省| 德安县| 苍山县| 宁南县| 工布江达县| 县级市| 潼关县| 银川市| 邮箱| 柘荣县| 永清县| 阜城县| 施甸县| 子长县| 鱼台县| 呼玛县|