新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM匯編語言(4) 指令、偽操作、偽指令學(xué)習(xí)

        ARM匯編語言(4) 指令、偽操作、偽指令學(xué)習(xí)

        作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
        LDR指令與LDR偽指令的4種形式:

        LDR R0,[R1]:指令,將R1指向的內(nèi)存地址存放的內(nèi)容加載到R0中;

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

        LDR R0,LABEL:指令,將標(biāo)號(hào)LABEL所代表的內(nèi)存地址處存放的內(nèi)容加載到R0中;

        LDR R0,=10000:偽指令,將常熟10000賦予R0,采用LDR指令+文字池的方式實(shí)現(xiàn);

        LDR R0,=LABEL:偽指令,將標(biāo)號(hào)LABEL所代表的內(nèi)存地址賦予R0;

        指令部分:

        偽操作部分:

        符號(hào)定義偽操作:定義變量,對(duì)變量進(jìn)行賦值,定義寄存器名稱

        GBLA:全局的算術(shù)變量,初始化為0;

        GBLL:全局的邏輯變量,初始化為{FALSE};

        GBLS:全局的串變量,初始化為“”;

        LCLA:局部的算術(shù)變量,初始化為0;

        LCLL:局部的邏輯變量,初始化為{FALSE};

        LCLS:局部的串變量,初始化為“”;

        SETA:給算術(shù)變量賦值;

        SETL:給邏輯變量賦值;

        SETS:給串變量賦值;

        RLIST:為一個(gè)通用寄存器列表定義名稱;

        CN:為一個(gè)協(xié)處理器的寄存器定義名稱;

        CP:為一個(gè)協(xié)處理器定義名稱;

        DN:為一個(gè)雙精度的VFP寄存器定義名稱;

        SN:為一個(gè)單精度的VFP寄存器定義名稱;

        FN:為一個(gè)FPA浮點(diǎn)寄存器定義名稱;

        數(shù)據(jù)定義偽操作

        LTORG:聲明一個(gè)數(shù)據(jù)緩沖池的開始;

        MAP:定義一個(gè)結(jié)構(gòu)化的內(nèi)存表的首地址,同義詞為^;

        FIELD:定義一個(gè)結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域,同義詞#;

        SPACE:分配一塊內(nèi)存單元,并用0初始化,同義詞%;

        {label} SPACE exprexpr表示分配的內(nèi)存字節(jié)數(shù);

        DCB:分配一段字節(jié)內(nèi)存單元,并用expr初始化之,同義詞=;

        {label} DCB expr, {expr}...expr是-128~255的數(shù)值或字符串;

        DCD,DCDU:分配一段字內(nèi)存單元,分配的內(nèi)存都是字對(duì)齊的,并用expr初始化之,同義詞&,DCDU分配的內(nèi)存單元不嚴(yán)格字對(duì)齊;

        DCDO:分配一段字內(nèi)存單元,分配的內(nèi)存都是字對(duì)齊的,并將每個(gè)字單元的內(nèi)容初始化為expr標(biāo)號(hào)基于靜態(tài)基址寄存器R9的偏移量;

        DCFD,DCFDU:

        DCFS,DCFSU:

        DCI:(ARM)分配一段字內(nèi)存單元,分配的內(nèi)存都是字對(duì)齊的,并用expr初始化;(Thumb)分配一段半字內(nèi)存單元,分配的內(nèi)存都是半字對(duì)齊的,并用expr初始化;

        DCQ,DCQU:

        DCW,DCWU:

        匯編控制偽操作

        IF,ELSE,ENDIF:根據(jù)條件將一段源代碼包括在匯編語言程序中或者將其排除在程序之外;

        IF logical expression

        instructions or directives

        ELSE

        instructions or directives

        ENDIF

        WHILE,WEND:根據(jù)條件重復(fù)匯編相同的或者幾乎相同的一段源代碼;

        WHILE logical expression

        instructions or directives

        WEND

        MACRO,MEND:定義宏定義體;

        MEXIT:從宏中跳轉(zhuǎn)出去;

        棧中數(shù)據(jù)幀描述偽操作;

        信息報(bào)告?zhèn)尾僮鳎?/p>

        其它偽操作:

        CODE16,CODE32:

        EQU:為數(shù)字常量,基于寄存器的值和程序中的標(biāo)號(hào)定義一個(gè)字符名稱,同義詞*;

        name EQU expr {, type}

        AREA:

        ENTRY:

        END:

        ALIGN:

        EXPORT:

        GLOBAL:

        IMPORT:

        EXTERN:

        GET:

        INCLUDE:

        INCBIN:

        KEEP:

        NOFP:

        REQUIRE:

        REQUIRE8:

        PRESERVE8:

        RN:

        ROUT:

        偽指令部分:偽指令不是真正的指令,在匯編編譯器對(duì)源程序進(jìn)行匯編處理時(shí)被替換成對(duì)應(yīng)的ARM或者Thumb指令;

        ADR(小范圍的地址讀取偽指令):將基于PC的地址值或者基于寄存器的地址值讀取到寄存器中;

        ADR{cond} register, expr

        expr是基于PC或者基于寄存器的地址表達(dá)式,取值范圍如下:

        地址值不是字對(duì)齊時(shí),取值范圍-255~255;

        地址值是字對(duì)齊時(shí),取值范圍-1020~1020;

        地址值是16字節(jié)對(duì)齊時(shí),取值范圍更大;

        ADRL(中等范圍的地址讀取偽指令):將基于PC的地址值或者基于寄存器的地址值讀取到寄存器中;

        ADRL{cond} register, expr

        expr是基于PC或者基于寄存器的地址表達(dá)式,取值范圍如下:

        地址不是字對(duì)齊時(shí),-64KB~64KB;

        地址是字對(duì)齊時(shí),-256KB~256KB;

        地址是16字節(jié)對(duì)齊時(shí),取值范圍更大;

        LDR:將一個(gè)32位的常數(shù)或者一個(gè)地址值讀取到寄存器中;

        LDR{cond} register, ={expr | label-expr}

        expr為32位常量;

        label-expr為基于PC的地址表達(dá)式或者外部表達(dá)式;

        NOP:匯編時(shí)被替換成ARM中的空操作;

        實(shí)例程序:

        1、

        AREA LDR_Code, CODE, READONLY
        ENTRY

        LDR r0, =src
        LDR r1, =dst
        MOV r2, r0
        MOV r3, r1
        MOV r5, #100
        LDR r6, =100
        LDR r7, =999999




        srcDCD 0, 1;, 2, 3, 4, 5, 6, 7, 8, 9
        dstDCD 0, 0;, 0, 0, 0, 0, 0, 0, 0, 0


        END

        反匯編代碼:

        $a
        LDR_Code
        0x00000000: e59f0024 $... LDR r0,0x2c
        0x00000004: e59f1024 $... LDR r1,0x30
        0x00000008: e1a02000 . .. MOV r2,r0
        0x0000000c: e1a03001 .0.. MOV r3,r1
        0x00000010: e3a05064 dP.. MOV r5,#0x64
        0x00000014: e3a06064 d`.. MOV r6,#0x64
        0x00000018: e59f7014 .p.. LDR r7,0x34
        src
        $d
        0x0000001c: 00000000 .... DCD 0
        0x00000020: 00000001 .... DCD 1
        dst
        0x00000024: 00000000 .... DCD 0
        0x00000028: 00000000 .... DCD 0
        0x0000002c: 0000001c .... DCD 28
        0x00000030: 00000024 $... DCD 36
        0x00000034: 000f423f ?B.. DCD 999999

        (1)為LDR偽指令生成的代碼,似乎有問題,不是基于PC的值,還是有默認(rèn)的規(guī)則?

        使用GNU ARM Assembly將上面的代碼重新實(shí)現(xiàn)一次:

        .section .text
        .global _start
        _start:
        LDR r0, =src
        LDR r1, =dst
        LDR r2, =1000
        LDR r3, =5555


        MOV r4, r2
        MOV r5, r3


        .section .data
        src: .word 0, 0
        dst: .word 0, 1

        編譯通過了,不確定代碼有沒有問題,后面再檢查

        將上面的代碼使用arm-none-eabi-as編譯不鏈接,然后使用arm-none-eabi-objdump反匯編:

        Disassembly of section .text:


        00000000 <_start>:
        0: e59f0010 ldr r0, [pc, #16] ; 18 <_start+0x18>
        4: e59f1010 ldr r1, [pc, #16] ; 1c <_start+0x1c>
        8: e3a02ffa mov r2, #1000 ; 0x3e8
        c: e59f300c ldr r3, [pc, #12] ; 20 <_start+0x20>
        10: e1a04002 mov r4, r2
        14: e1a05003 mov r5, r3
        18: 00000000 andeq r0, r0, r0
        1c: 00000008 andeq r0, r0, r8
        20: 000015b3 strheq r1, [r0], -r3

        誠如文檔中對(duì)LDR的介紹:

        LDR r0, =src
        LDR r1, =dst
        LDR r2, =1000
        LDR r3, =5555

        這四條命令都進(jìn)行了處理,以LDR r0, =src為例:

        0: e59f0010 ldr r0, [pc, #16] ; 18 <_start+0x18>

        src的值被存儲(chǔ),ldr指令將[pc, #16]地址中的值加載到寄存器r0中,

        ARM處理器中,pc的值為當(dāng)前執(zhí)行的指令的地址值加上8,因此,執(zhí)行該條

        指令時(shí),pc的值為8,此時(shí)pc加上16,則為十進(jìn)制的24,十六進(jìn)制的

        0x18,但是此時(shí)地址單元0x18中存儲(chǔ)的卻是一條指令:

        andeq r0, r0, r0

        為什么?

        將之前編譯生成的.o文件使用arm-none-eabi-ld進(jìn)行連接,生成可執(zhí)行文件,

        然后反匯編,此時(shí)代碼變?yōu)椋?/p>

        Disassembly of section .text:


        00008000 <_start>:
        8000: e59f0010 ldr r0, [pc, #16] ; 8018 <_start+0x18>
        8004: e59f1010 ldr r1, [pc, #16] ; 801c <_start+0x1c>
        8008: e3a02ffa mov r2, #1000 ; 0x3e8
        800c: e59f300c ldr r3, [pc, #12] ; 8020 <_start+0x20>
        8010: e1a04002 mov r4, r2
        8014: e1a05003 mov r5, r3


        8018: 00010024 andeq r0, r1, r4, lsr #32
        801c: 0001002c andeq r0, r1, ip, lsr #32
        8020: 000015b3 strheq r1, [r0], -r3

        此時(shí),src的值應(yīng)該存放在0x8000 + 8 + 16,8和16都是十進(jìn)制的,因此應(yīng)該是0x8018,

        但是0x8018地址單元中為:

        andeq r0, r1, r4, lsr #32

        lsr在上一篇尋址方式中有所介紹,此時(shí)r4中的值通過上面的指令可知為十進(jìn)制的1000,十六進(jìn)制的0x3E8,

        0x3E8的二進(jìn)制:

        0000 0000 0000 0000 0000 0011 1110 1000,執(zhí)行l(wèi)sr #32操作,右移32位,則變?yōu)?,

        r1中此時(shí)不管是什么值,AND指令執(zhí)行按位取與操作,指令的執(zhí)行結(jié)果自然是0,存放到r0寄存器中?

        此處應(yīng)該是個(gè)pool?為什么是指令?

        (2)$a、$d分別表示什么意思?

        摘錄自:Using asThegnuAssembler的Mapping Symbols章節(jié)

        The ARM ELF specification requires that special symbols be inserted into object files to
        mark certain features:
        $a At the start of a region of code containing ARM instructions.
        $t At the start of a region of code containing THUMB instructions.
        $d At the start of a region of data.

        待補(bǔ)充...



        關(guān)鍵詞: ARM匯編語言偽操作偽指

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 广宗县| 南丰县| 彰化市| 淳安县| 富顺县| 和林格尔县| 广元市| 佛教| 荥经县| 东光县| 晋江市| 秦安县| 宝清县| 尤溪县| 望城县| 会同县| 当阳市| 金阳县| 广元市| 莱西市| 修水县| 长兴县| 彭山县| 东至县| 桦南县| 乌兰浩特市| 凤凰县| 大安市| 青铜峡市| 安龙县| 翁牛特旗| 漾濞| 建宁县| 岚皋县| 乌海市| 当阳市| 潼关县| 嘉义县| 南皮县| 霍林郭勒市| 沐川县|