最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

ARM裸機(jī)開發(fā)篇2:ARM微處理器指令系統(tǒng)(一)

2021-10-25 11:14 作者:華清遠(yuǎn)見研發(fā)中心  | 我要投稿

寫在前面:

本文章為《ARM Cortex-A7裸機(jī)開發(fā)篇》系列中的一篇,全系列總計(jì)11篇。筆者使用的開發(fā)平臺(tái)為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。

針對(duì)FS-MP1A開發(fā)板,除了Cortex-A7裸機(jī)開發(fā)篇外,還包括其他多系列教程,包括Cortex-M4開發(fā)篇、FreeRTOS篇、Linux基礎(chǔ)及應(yīng)用開發(fā)篇、Linux系統(tǒng)移植篇、Linux驅(qū)動(dòng)開發(fā)篇、硬件設(shè)計(jì)篇、人工智能機(jī)器視覺篇、Qt應(yīng)用編程篇、Qt綜合項(xiàng)目實(shí)戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群483143191,感謝關(guān)注。

FS-MP1A開發(fā)板詳情介紹:item.taobao.com/item.ht

ARM微處理器指令系統(tǒng)

本章主要介紹ARM匯編語言。主要內(nèi)容如下:

  • ARM處理器的尋址方式。

  • ARM處理器的指令集。

ARM處理器尋址方式

ARM指令的尋址方式分為數(shù)據(jù)處理指令尋址方式和內(nèi)存訪問指令尋址方式。

數(shù)據(jù)處理指令尋址方式

數(shù)據(jù)處理指令的基本語法格式如下:

<opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>

其中,<shifter_operand>有11種形式,如表所示。

表 <shifter_operand>的尋址方式

數(shù)據(jù)處理指令尋址方式可以分為以下幾種。

    1. 立即數(shù)尋址方式。

    2. 寄存器尋址方式。

    3. 寄存器移位尋址方式。




    1. 立即數(shù)尋址方式

    指令中的立即數(shù)是由一個(gè)8bit的常數(shù)移動(dòng)4bit偶數(shù)位(0,2,4,…,26,28,30)得到的。所以,每一條指令都包含一個(gè)8bit的常數(shù)X和移位值Y,得到的立即數(shù) = X循環(huán)右移(2×Y),如圖所示。

    下面列舉了一些有效的立即數(shù):

    0xFF、0x104、0xFF0、0xFF00、0xFF000、0xFF000000、0xF000000F

    下面是一些無效的立即數(shù):

    0x101、0x102、0xFF1、0xFF04、0xFF003、0xFFFFFFFF、0xF000001F

    下面是一些應(yīng)用立即數(shù)的指令:

    MOV R0,#0 ;送0到R0

    ADD R3,R3,#1 ;R3的值加1

    CMP R7,#1000 ;將R7的值和1000比較

    BIC R9,R8,#0xFF00 ;將R8中8~15位清零,結(jié)果保存在R9中

    1. 寄存器尋址方式

    寄存器的值可以被直接用于數(shù)據(jù)操作指令,這種尋址方式是各類處理器經(jīng)常采用的一種方式,也是一種執(zhí)行效率較高的尋址方式,如:

    MOV R2,R0 ;R0的值送R2

    ADD R4,R3,R2 ;R2加R3,結(jié)果送R4

    CMP R7,R8 ;比較R7和R8的值

    1. 寄存器移位尋址方式

    寄存器的值在被送到ALU之前,可以事先經(jīng)過桶形移位寄存器的處理。預(yù)處理和移位發(fā)生在同一周期內(nèi),所以有效地使用移位寄存器,可以增加代碼的執(zhí)行效率。

    下面是一些在指令中使用了移位操作的例子:

    ADD R2,R0,R1,LSR #5

    MOV R1,R0,LSL #2

    RSB R9,R5,R5,LSL #1

    SUB R1,R2,R0,LSR #4

    MOV R2,R4,ROR R0

    內(nèi)存訪問指令尋址方式

    內(nèi)存訪問指令的尋址方式可以分為以下幾種。

    1. 字及無符號(hào)字節(jié)的Load/Store指令的尋址方式。

    2. 雜類Load/Store指令的尋址方式。

    3. 批量Load/Store指令的尋址方式。

    4. 協(xié)處理器Load/Store指令的尋址方式。

    5. 字及無符號(hào)字節(jié)的Load/Store指令的尋址方式

    字及無符號(hào)字節(jié)的Load/Store指令語法格式如下:

    LDR|STR{<cond>}{B}{T} <Rd>,<addressing_mode>

    其中,<addressing_mode>共有9種尋址方式,如表所示。

    上表中,“!”表示完成數(shù)據(jù)傳輸后要更新基址寄存器。

    1. 雜類Load/Store指令的尋址方式

    使用該類尋址方式的指令的語法格式如下:

    LDR|STR{<cond>}H|SH|SB|D <Rd>,<addressing_mode>

    使用該類尋址方式的指令包括(有符號(hào)/無符號(hào))半字Load/Store指令、有符號(hào)字節(jié)Load/Store指令和雙字Load/Store指令。

    該類尋址方式分為6種類型,如表所示。

    格 式模 式1[Rn,#±<offset_8>]立即數(shù)偏移尋址(Immediate offset)2[Rn,±Rm]寄存器偏移尋址(Register offset)3[Rn,#±< offset_8>]!立即數(shù)前索引尋址(Immediate pre-indexed)4[Rn,±Rm]!寄存器前索引尋址(Register post-indexed)5[Rn],#±< offset_8>立即數(shù)后索引尋址(Immediate post-indexed)6[Rn],±<Rm>寄存器后索引尋址(Register post-indexed)

    1. 批量Load/Store指令尋址方式

    批量Load/Store指令將一片連續(xù)內(nèi)存單元的數(shù)據(jù)加載到通用寄存器組中或?qū)⒁唤M通用寄存器的數(shù)據(jù)存儲(chǔ)到內(nèi)存單元中。

    批量Load/Store指令的尋址模式產(chǎn)生一個(gè)內(nèi)存單元的地址范圍,指令寄存器和內(nèi)存單元的對(duì)應(yīng)關(guān)系滿足這樣的規(guī)則,即編號(hào)低的寄存器對(duì)應(yīng)于內(nèi)存中低地址單元,編號(hào)高的寄存器對(duì)應(yīng)于內(nèi)存中的高地址單元。

    該類指令的語法格式如下:

    LDM|STM{<cond>}<addressing_mode> <Rn>{!},<registers><^>

    該類指令的尋址方式如表所示。

    格 式模 式1IA(Increment After)后遞增方式2IB(Increment Before)先遞增方式3DA(Decrement After)后遞減方式4DB(Decrement Before)先遞減方式

    1. 堆棧操作尋址方式

    堆棧操作尋址方式和批量Load/Store指令尋址方式十分類似。但對(duì)于堆棧的操作,數(shù)據(jù)寫入內(nèi)存和從內(nèi)存中讀出要使用不同的尋址模式,因?yàn)檫M(jìn)棧操作(pop)和出棧操作(push)要在不同的方向上調(diào)整堆棧。

    下面詳細(xì)討論如何使用合適的尋址方式實(shí)現(xiàn)數(shù)據(jù)的堆棧操作。

    根據(jù)不同的尋址方式,將堆棧分為以下4種。

      1. Full棧:堆棧指針指向棧頂元素(last used location)。

      2. Empty棧:堆棧指針指向第一個(gè)可用元素(the first unused location)。

      3. 遞減棧:堆棧向內(nèi)存地址減小的方向生長(zhǎng)。

      4. 遞增棧:堆棧向內(nèi)存地址增加的方向生長(zhǎng)。




      根據(jù)堆棧的不同種類,將其尋址方式分為以下4種。

        1. 滿遞減FD(Full Descending)。

        2. 空遞減ED(Empty Descending)。

        3. 滿遞增FA(Full Ascending)。

        4. 空遞增EA(Empty Ascending)。

        如表所示列出了堆棧的尋址方式和批量Load/Store指令尋址方式的對(duì)應(yīng)關(guān)系。

        批量數(shù)據(jù)尋址方式堆棧尋址方式L位P位U位LDMDALDMFA100LDMIALDMFD101LDMDBLDMEA110LDMIBLDMED111STMDASTMED000STMIASTMEA001STMDBSTMFD010STMIBSTMFA011

        1. 協(xié)處理器Load/Store尋址方式

        協(xié)處理器Load/Store指令的語法格式如下:

        <opcode>{<cond>}{L} <coproc>,<CRd>,<addressing_mode>


        ARM處理器指令集


        數(shù)據(jù)操作指令

        數(shù)據(jù)操作指令是指對(duì)存放在寄存器中的數(shù)據(jù)進(jìn)行操作的指令。主要包括數(shù)據(jù)傳送指令、算術(shù)指令、邏輯指令、比較與測(cè)試指令及乘法指令。

        如果在數(shù)據(jù)處理指令前使用S前綴,指令的執(zhí)行結(jié)果將會(huì)影響CPSR中的標(biāo)志位。數(shù)據(jù)處理指令如表所示。

        助 記 符操 作行 為MOV數(shù)據(jù)傳送MVN數(shù)據(jù)取反傳送AND邏輯與Rd:=Rn AND op2EOR邏輯異或Rd:=Rn EOR op2SUB減Rd:=Rn ? op2RSB翻轉(zhuǎn)減Rd:=op2 ? RnADD加Rd:=Rn + op2ADC帶進(jìn)位的加Rd:=Rn + op2 + CSBC帶進(jìn)位的減Rd:=Rn? op2 + C ? 1RSC帶進(jìn)位的翻轉(zhuǎn)減Rd:=op2 ? Rn + C ? 1TST測(cè)試Rn AND op2并更新標(biāo)志位TEQ測(cè)試相等Rn EOR op2并更新標(biāo)志位CMP比較Rn?op2并更新標(biāo)志位CMN負(fù)數(shù)比較Rn+op2并更新標(biāo)志位ORR邏輯或Rd:=Rn OR op2BIC位清0Rd:=Rn AND NOT(op2)


        1. MOV指令

        MOV指令是最簡(jiǎn)單的ARM指令,執(zhí)行的結(jié)果就是把一個(gè)數(shù)N送到目標(biāo)寄存器Rd,其中N可以是寄存器,也可以是立即數(shù)。

        MOV指令多用于設(shè)置初始值或者在寄存器間傳送數(shù)據(jù)。

        MOV指令將移位碼(shifter_operand)表示的數(shù)據(jù)傳送到目的寄存器Rd,并根據(jù)操作的結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。

        1. 指令的語法格式:

        MOV{<cond>}{S} <Rd>,<shifter_operand>

        1. 指令舉例:

        MOV R0, R0 ; R0 = R0… NOP 指令

        MOV R0, R0, LSL#3 ; R0 = R0 * 8

        如果R15是目的寄存器,將修改程序計(jì)數(shù)器或標(biāo)志。這用于被調(diào)用的子函數(shù)結(jié)束后返回到調(diào)用代碼,方法是把連接寄存器的內(nèi)容傳送到R15。

        MOV PC, R14 ; 退出到調(diào)用者,用于普通函數(shù)返回,PC即是R15

        MOVS PC, R14 ; 退出到調(diào)用者并恢復(fù)標(biāo)志位,用于異常函數(shù)返回

        1. 指令的使用如下。

        MOV指令主要完成以下功能。

        將數(shù)據(jù)從一個(gè)寄存器傳送到另一個(gè)寄存器。

        將一個(gè)常數(shù)值傳送到寄存器中。

        實(shí)現(xiàn)無算術(shù)和邏輯運(yùn)算的單純移位操作,操作數(shù)乘以2n可以用左移n位來實(shí)現(xiàn)。

        當(dāng)PC(R15)用做目的寄存器時(shí),可以實(shí)現(xiàn)程序跳轉(zhuǎn)。如“MOV PC,LR”,所以這種跳轉(zhuǎn)可以實(shí)現(xiàn)子程序調(diào)用及從子程序返回,代替指令“B,BL”。

        當(dāng)PC作為目標(biāo)寄存器且指令中S位被設(shè)置時(shí),指令在執(zhí)行跳轉(zhuǎn)操作的同時(shí),將當(dāng)前處理器模式的SPSR寄存器的內(nèi)容復(fù)制到CPSR中。這種指令“MOVS PC LR”可以實(shí)現(xiàn)從某些異常中斷中返回。

        1. MVN指令

        MVN是反相傳送(Move Negative)指令。它將操作數(shù)的反碼傳送到目的寄存器。

        MVN指令多用于向寄存器傳送一個(gè)負(fù)數(shù)或生成位掩碼。

        MVN指令將shifter_operand表示的數(shù)據(jù)的反碼傳送到目的寄存器Rd,并根據(jù)操作結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。

        1. 指令的語法格式:

        MNV{<cond>}{S} <Rd>,<shifter_operand>

        指令舉例如下

        1. MVN指令和MOV指令相同,也可以把一個(gè)數(shù)N送到目標(biāo)寄存器Rd,其中N可以是立即數(shù),也可以是寄存器。這是邏輯非操作而不是算術(shù)操作,這個(gè)取反的值加1才是它的取負(fù)的值。

        MVN R0, #4 ; R0 = -5

        MVN R0, #0 ; R0 = -1

        1. 指令的使用如下。

        MVN指令主要完成以下功能:

        向寄存器中傳送一個(gè)負(fù)數(shù)。

        生成位掩碼(Bit Mask)。

        求一個(gè)數(shù)的反碼。

        1. AND指令

        AND指令將shifter_operand表示的數(shù)值與寄存器Rn的值按位(bitwise)做邏輯與操作,并將結(jié)果保存到目標(biāo)寄存器Rd中,同時(shí)根據(jù)操作的結(jié)果更新CPSR寄存器。

          1. 指令的語法格式:




          AND{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

            1. 指令舉例如下。


            2. 保留R0中的0位和1位,丟棄其余的位。

            AND R0, R0, #3

            1. R2 = R1&R3。

            AND R2,R1,R3

            1. R0 = R0&0x01,取出最低位數(shù)據(jù)。

            ANDS R0,R0,#0x01

            1. EOR指令

            EOR(Exclusive OR)指令將寄存器Rn中的值和shifter_operand的值執(zhí)行按位“異或”操作,并將執(zhí)行結(jié)果存儲(chǔ)到目的寄存器Rd中,同時(shí)根據(jù)指令的執(zhí)行結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。

            1. 指令的語法格式:

            EOR{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

            1. 指令舉例:

            2. 反轉(zhuǎn)R0中的位0和1。

            EOR R0, R0, #3

            1. 將R1的低4位取反。

            EOR R1,R1,#0x0F

            1. R2 = R1∧R0。

            EOR R2,R1,R0

            1. 將R5和0x01進(jìn)行邏輯異或,結(jié)果保存到R0,并根據(jù)執(zhí)行結(jié)果設(shè)置標(biāo)志位。

            EORS R0,R5,#0x01

            1. SUB指令

            SUB(Subtract)指令從寄存器Rn中減去shifter_operand表示的數(shù)值,并將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

              1. 指令的語法格式:




              SUB{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                1. SUB指令舉例:

                2. R0 = R1 ? R2。

                SUB R0, R1, R2

                1. R0 = R1 ? 256。

                SUB R0, R1, #256

                1. R0 = R2? (R3<<1)。

                SUB R0, R2, R3,LSL#1

                1. RSB指令

                RSB(Reverse Subtract)指令從寄存器shifter_operand中減去Rn表示的數(shù)值,并將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

                  1. 指令的語法格式:




                  RSB{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                    1. RSB指令舉例:




                    下面的指令序列可以求一個(gè)64位數(shù)值的負(fù)數(shù)。64位數(shù)放在寄存器R0與R1中,其負(fù)數(shù)放在R2和R3中。其中R0與R2中放低32位值。

                    RSBS R2,R0,#0

                    RSC R3,R1,#0

                    1. ADD指令

                    ADD指令將寄存器shifter_operand的值加上Rn表示的數(shù)值,并將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

                      1. 指令的語法格式:




                      ADD{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                        1. ADD指令舉例:




                        ADD R0, R1, R2 ; R0 = R1 + R2

                        ADD R0, R1, #256 ; R0 = R1 + 256

                        ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1)

                        1. ADC指令

                        ADC指令將寄存器shifter_operand的值加上Rn表示的數(shù)值,再加上CPSR中的C條件標(biāo)志位的值,將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

                          1. 指令的語法格式:




                          ADC{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                            1. ADC指令舉例:




                            ADC指令將把兩個(gè)操作數(shù)加起來,并把結(jié)果放置到目的寄存器中。它使用一個(gè)進(jìn)位標(biāo)志位,這樣就可以做比32位大的加法。下面的例子將加兩個(gè)128位的數(shù)。

                            128位結(jié)果:寄存器R0、R1、R2和R3。

                            第一個(gè)128位數(shù):寄存器R4、R5、R6和R7。

                            第二個(gè)128位數(shù):寄存器R8、R9、R10和R11。

                            ADDS R0, R4, R8 ;加低端的字

                            ADCS R1, R5, R9 ;加下一個(gè)字,帶進(jìn)位

                            ADCS R2, R6, R10 ;加第三個(gè)字,帶進(jìn)位

                            ADCS R3, R7, R11 ;加高端的字,帶進(jìn)位

                            1. SBC指令

                            SBC(Subtract with Carry)指令用于執(zhí)行操作數(shù)大于32位時(shí)的減法操作。該指令從寄存器Rn中減去shifter_operand表示的數(shù)值,再減去寄存器CPSR中C條件標(biāo)志位的反碼[NOT(Carry flag)],并將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

                              1. 指令的語法格式:




                              SBC{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                                1. SBC指令舉例:




                                下面的程序使用SBC實(shí)現(xiàn)64位減法,(R1,R0)?(R3,R2),結(jié)果存放到(R1,R0)。

                                SUBS R0,R0,R2

                                SBCS R1,R1,R3

                                1. RSC指令

                                RSC(Reverse Subtract with Carry)指令從寄存器shifter_operand中減去Rn表示的數(shù)值,再減去寄存器CPSR中C條件標(biāo)志位的反碼[NOT(Carry Flag)],并將結(jié)果保存到目標(biāo)寄存器Rd中,并根據(jù)指令的執(zhí)行結(jié)果設(shè)置CPSR中相應(yīng)的標(biāo)志位。

                                  1. 指令的語法格式:




                                  RSC{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                                    1. RSC指令舉例:




                                    下面的程序使用RSC指令實(shí)現(xiàn)求64位數(shù)值的負(fù)數(shù)。

                                    RSBS R2,R0,#0

                                    RSC R3,R1,#0

                                    1. TST測(cè)試指令

                                    TST(Test)測(cè)試指令用于將一個(gè)寄存器的值和一個(gè)算術(shù)值進(jìn)行比較。條件標(biāo)志位根據(jù)兩個(gè)操作數(shù)做“邏輯與”后的結(jié)果設(shè)置。

                                      1. 指令的語法格式:




                                      TST{<cond>} <Rn>,<shifter_operand>

                                        1. TST指令舉例:




                                        TST指令類似于CMP指令,不產(chǎn)生放置到目的寄存器中的結(jié)果。而是在給出的兩個(gè)操作數(shù)上進(jìn)行操作并把結(jié)果反映到狀態(tài)標(biāo)志上。使用TST指令來檢查是否設(shè)置了特定的位。操作數(shù)1是要測(cè)試的數(shù)據(jù)字而操作數(shù)2是一個(gè)位掩碼。經(jīng)過測(cè)試后,如果匹配則設(shè)置Zero標(biāo)志,否則清除它。與CMP指令一樣,該指令不需要指定S后綴。

                                        下面的指令測(cè)試在R0中是否設(shè)置了位0。

                                        TST R0, #1

                                        1. TEQ指令

                                        TEQ(Test Equivalence)指令用于將一個(gè)寄存器的值和一個(gè)算術(shù)值做比較。條件標(biāo)志位根據(jù)兩個(gè)操作數(shù)做“邏輯異或”后的結(jié)果設(shè)置。以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。

                                          1. 指令的語法格式:




                                          TEQ{<cond>} <Rn>,<shifter_operand>

                                            1. TEQ指令舉例:




                                            下面的指令是比較R0和R1是否相等,該指令不影響CPSR中的V位和C位。

                                            TEQ R0,R1

                                            TST指令與EORS指令的區(qū)別在于TST指令不保存運(yùn)算結(jié)果。使用TEQ進(jìn)行相等測(cè)試,常與EQ和NE條件碼配合使用,當(dāng)兩個(gè)數(shù)據(jù)相等時(shí),條件碼EQ有效;否則條件碼NE有效。

                                            1. CMP指令

                                            CMP(Compare)指令使用寄存器Rn的值減去operand2的值,根據(jù)操作的結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位,以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。

                                              1. 指令的語法格式:




                                              CMP{<cond>} <Rn>,<shifter_operand>

                                                1. CMP指令舉例:




                                                CMP指令允許把一個(gè)寄存器的內(nèi)容與另一個(gè)寄存器的內(nèi)容或立即值進(jìn)行比較,更改狀態(tài)標(biāo)志來允許進(jìn)行條件執(zhí)行。它進(jìn)行一次減法,但不存儲(chǔ)結(jié)果,而是正確地更改標(biāo)志位。標(biāo)志位表示的是操作數(shù)1與操作數(shù)2比較的結(jié)果(其值可能為大于、小于、相等)。如果操作數(shù)1大于操作數(shù)2,則此后的有GT后綴的指令將可以執(zhí)行。

                                                顯然,CMP不需要顯式地指定S后綴來更改狀態(tài)標(biāo)志。

                                                1. 下面的指令是比較R1和立即數(shù)10并設(shè)置相關(guān)的標(biāo)志位。

                                                CMP R1,#10

                                                1. 下面的指令是比較寄存器R1和R2中的值并設(shè)置相關(guān)的標(biāo)志位。

                                                CMP R1,R2

                                                通過上面的例子可以看出,CMP指令與SUBS指令的區(qū)別在于CMP指令不保存運(yùn)算結(jié)果,在進(jìn)行兩個(gè)數(shù)據(jù)大小判斷時(shí),常用CMP指令及相應(yīng)的條件碼來進(jìn)行操作。

                                                1. CMN指令

                                                CMN(Compare Negative)指令使用寄存器Rn的值減去operand2的負(fù)數(shù)值(加上operand2),根據(jù)操作的結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位,以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行。

                                                  1. 指令的語法格式:




                                                  CMN{<cond>} <Rn>,<shifter_operand>

                                                    1. CMN指令舉例:




                                                    CMN指令將寄存器Rn中的值加上shifter_operand表示的數(shù)值,根據(jù)加法的結(jié)果設(shè)置CPSR中相應(yīng)的條件標(biāo)志位。寄存器Rn中的值加上shifter_operand的操作結(jié)果對(duì)CPSR中條件標(biāo)志位的影響,與寄存器Rn中的值減去shifter_operand的操作結(jié)果的相反數(shù)對(duì)CPSR中條件標(biāo)志位的影響有細(xì)微差別。當(dāng)?shù)?個(gè)操作數(shù)為0或者為0x80000000時(shí)兩者結(jié)果不同。比如下面兩條指令。

                                                    CMP Rn,#0

                                                    CMN Rn,#0

                                                    第1條指令使標(biāo)志位C值為1,第2條指令使標(biāo)志位C值為0。

                                                    下面的指令使R0值加1,判斷R0是否為1的補(bǔ)碼,若是,則Z置位。

                                                    CMN R0,#1

                                                    1. ORR指令

                                                    ORR(Logical OR)為邏輯或操作指令,它將第2個(gè)源操作數(shù)shifter_operand的值與寄存器Rn的值按位做“邏輯或”操作,結(jié)果保存到Rd中。

                                                      1. 指令的語法格式:




                                                      ORR{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                                                        1. ORR指令舉例:




                                                        1. 設(shè)置R0中位0和1。

                                                        ORR R0, R0, #3

                                                        1. 將R0的低4位置1。

                                                        ORR R0,R0,#0x0F

                                                        1. 使用ORR指令將R2的高8位數(shù)據(jù)移入到R3的低8位中。

                                                        MOV R1,R2,LSR #4

                                                        ORR R3,R1,R3,LSL #8

                                                        1. BIC位清零指令

                                                        BIC(Bit Clear)位清零指令,將寄存器Rn的值與第2個(gè)源操作數(shù)shifter_operand的值的反碼按位做“邏輯與”操作,結(jié)果保存到Rd中。

                                                          1. 指令的語法格式:




                                                          BIC{<cond>}{S} <Rd>,<Rn>,<shifter_operand>

                                                            1. BIC指令舉例:




                                                            1. 清除R0中的位0、1和3,保持其余的不變。

                                                            BIC R0, R0, #0x1011

                                                            1. 將R3的反碼和R2做“邏輯與”操作,結(jié)果保存到R1中。

                                                            BIC R1,R2,R3

                                                            乘法指令

                                                            ARM乘法指令完成兩個(gè)數(shù)據(jù)的乘法。兩個(gè)32位二進(jìn)制數(shù)相乘的結(jié)果是64位的積。在有些ARM的處理器版本中,將乘積的結(jié)果保存到兩個(gè)獨(dú)立的寄存器中。另外一些版本只將最低有效32位存放到一個(gè)寄存器中。無論是哪種版本的處理器,都有乘—累加的變型指令,將乘積連續(xù)累加得到總和。而且有符號(hào)數(shù)和無符號(hào)數(shù)都能使用。對(duì)于有符號(hào)數(shù)和無符號(hào)數(shù),結(jié)果的最低有效位是一樣的。因此,對(duì)于只保留32位結(jié)果的乘法指令,不需要區(qū)分有符號(hào)數(shù)和無符號(hào)數(shù)這兩種情況。

                                                            如表所示為各種形式乘法指令的功能。


                                                            操作碼[23∶21]助 記 符意 義操 作000MUL乘(保留32位結(jié)果)Rd:=(Rm×Rs)[31∶0]001MLA乘—累加(保留32位結(jié)果)Rd:=(Rm×Rs+Rn)[31∶0]100UMULL無符號(hào)數(shù)長(zhǎng)乘RdHi:RdLo:=Rm×Rs101UMLAL無符號(hào)長(zhǎng)乘—累加RdHi:RdLo:+=Rm×Rs110SMULL有符號(hào)數(shù)長(zhǎng)乘RdHi:RdLo:=Rm×Rs111SMLAL有符號(hào)數(shù)長(zhǎng)乘—累加RdHi:RdLo:+=Rm×Rs

                                                            其中:

                                                              1. “RdHi:RdLo”是由RdHi(最高有效32位)和RdLo(最低有效32位)連接形成的64位數(shù),“[31:0]”只選取結(jié)果的最低有效32位。

                                                              2. 簡(jiǎn)單的賦值由“:=”表示。

                                                              3. 累加(將右邊加到左邊)是由“+ =”表示。




                                                              各個(gè)乘法指令中的位S(參考下文具體指令的語法格式)控制條件碼的設(shè)置會(huì)產(chǎn)生以下結(jié)果。

                                                              1. 對(duì)于產(chǎn)生32位結(jié)果的指令形式,將標(biāo)志位N設(shè)置為Rd的第31位的值;對(duì)于產(chǎn)生長(zhǎng)結(jié)果的指令形式,將其設(shè)置為RdHi的第31位的值。

                                                              2. 對(duì)于產(chǎn)生32位結(jié)果的指令形式,如果Rd等于零,則標(biāo)志位Z置位;對(duì)于產(chǎn)生長(zhǎng)結(jié)果的指令形式,RdHi和RdLo同時(shí)為零時(shí),標(biāo)志位Z置位。

                                                              3. 將標(biāo)志位C設(shè)置成無意義的值。

                                                              4. 標(biāo)志位V不變。

                                                              5. MUL指令

                                                              MUL(Multiply)32位乘法指令將Rm和Rs中的值相乘,結(jié)果的最低32位保存到Rd中。

                                                                1. 指令的語法格式:




                                                                MUL{<cond>}{S} <Rd>,<Rm>,<Rs>

                                                                  1. 指令舉例:




                                                                  1. R1 = R2 × R3。

                                                                  MUL R1, R2, R3

                                                                  1. R0 = R3 × R7,同時(shí)設(shè)置CPSR中的N位和Z位。

                                                                  MULS R0, R3, R7

                                                                  1. MLA指令

                                                                  MLA(Multiply Accumulate)32位乘—累加指令將Rm和Rs中的值相乘,再將乘積加上第3個(gè)操作數(shù),結(jié)果的最低32位保存到Rd中。

                                                                    1. 指令的語法格式:




                                                                    MLA{<cond>}{S} <Rd>,<Rm>,<Rs>,<Rn>

                                                                      1. 指令舉例:




                                                                      下面的指令完成R1 = R2×R3 + 10的操作。

                                                                      MOV R0, #0x0A

                                                                      MLA R1, R2, R3, R0

                                                                      1. UMULL指令

                                                                      UMULL(Unsigned Multiply Long)為64位無符號(hào)乘法指令。它將Rm和Rs中的值做無符號(hào)數(shù)相乘,結(jié)果的低32位保存到RsLo中,高32位保存到RdHi中。

                                                                        1. 指令的語法格式:




                                                                        UMULL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs>

                                                                          1. 指令舉例:




                                                                          下面的指令完成(R1,R0) = R5 × R8操作。

                                                                          UMULL R0, R1, R5, R8;

                                                                          1. UMLAL指令

                                                                          UMLAL(Unsigned Multiply Accumulate Long)為64位無符號(hào)長(zhǎng)乘—累加指令。指令將Rm和Rs中的值做無符號(hào)數(shù)相乘,64位乘積與RdHi、RdLo相加,結(jié)果的低32位保存到RsLo中,高32位保存到RdHi中。

                                                                            1. 指令的語法格式:




                                                                            UMALL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs>

                                                                              1. 指令舉例:




                                                                              下面的指令完成(R1,R0) = R5 × R8+(R1,R0)操作。

                                                                              UMLAL R0, R1, R5,R8;

                                                                              1. SMULL指令

                                                                              SMULL(Signed Multiply Long)為64位有符號(hào)長(zhǎng)乘法指令。指令將Rm和Rs中的值做有符號(hào)數(shù)相乘,結(jié)果的低32位保存到RsLo中,高32位保存到RdHi中。

                                                                                1. 指令的語法格式:




                                                                                SMULL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs>

                                                                                  1. 指令舉例:




                                                                                  下面的指令完成(R3,R2) = R7 × R6操作。

                                                                                  SMULL R2, R3, R7,R6;

                                                                                  1. SMLAL指令

                                                                                  SMLAL(Signed Multiply Accumulate Long)為64位有符號(hào)長(zhǎng)乘—累加指令。指令將Rm和Rs中的值做有符號(hào)數(shù)相乘,64位乘積與RdHi、RdLo相加,結(jié)果的低32位保存到RsLo中,高32位保存到RdHi中。

                                                                                    1. 指令的語法格式:




                                                                                    SMLAL{<cond>}{S} <RdLo>,<RdHi>,<Rm>,<Rs>

                                                                                      1. 指令舉例:




                                                                                      下面的指令完成(R3,R2) = R7 × R6 +(R3,R2)操作。

                                                                                      SMLAL R2, R3, R7,R6;

                                                                                      Load/Store指令

                                                                                      Load/Store內(nèi)存訪問指令在ARM寄存器和存儲(chǔ)器之間傳送數(shù)據(jù)。ARM指令中有3種基本的數(shù)據(jù)傳送指令。

                                                                                        1. 單寄存器Load/Store指令(Single Register),這些指令在ARM寄存器和存儲(chǔ)器之間提供更靈活的單數(shù)據(jù)項(xiàng)傳送方式。數(shù)據(jù)項(xiàng)可以是字節(jié)、16位半字或32位字。

                                                                                        2. 多寄存器Load/Store內(nèi)存訪問指令。這些指令的靈活性比單寄存器傳送指令差,但可以使大量的數(shù)據(jù)更有效地傳送。它們用于進(jìn)程的進(jìn)入和退出、保存和恢復(fù)工作寄存器及復(fù)制存儲(chǔ)器中的一塊數(shù)據(jù)。

                                                                                        3. 單寄存器交換指令(Single Register Swap)。這些指令允許寄存器和存儲(chǔ)器中的數(shù)值進(jìn)行交換,在一條指令中有效地完成Load/Store操作。它們?cè)谟脩艏?jí)編程中很少用到。它的主要用途是在多處理器系統(tǒng)中實(shí)現(xiàn)信號(hào)量(Semaphores)的操作,以保證不會(huì)同時(shí)訪問公用的數(shù)據(jù)結(jié)構(gòu)。

                                                                                        4. 單寄存器的Load/Store指令,這種指令用于把單一的數(shù)據(jù)傳入或者傳出一個(gè)寄存器。支持的數(shù)據(jù)類型有字節(jié)(8位)、半字(16位)和字(32位)。




                                                                                        1. 單寄存器的Load/Store指令

                                                                                        如表所示列出了所有單寄存器的Load/Store指令。

                                                                                        指 令作 用操 作LDR把存儲(chǔ)器中的一個(gè)字裝入一個(gè)寄存器Rd←mem32[address]STR將寄存器中的字保存到存儲(chǔ)器Rd→mem32[address]LDRB把一個(gè)字節(jié)裝入一個(gè)寄存器Rd←mem8[address]STRB將寄存器中的低8位字節(jié)保存到存儲(chǔ)器Rd→mem8[address]LDRH把一個(gè)半字裝入一個(gè)寄存器Rd←mem16[address]STRH將寄存器中的低16位半字保存到存儲(chǔ)器Rd→mem16[address]LDRBT用戶模式下將一個(gè)字節(jié)裝入寄存器Rd←mem8[address] under user modeSTRBT用戶模式下將寄存器中的低8位字節(jié)保存到存儲(chǔ)器Rd→mem8[address] under user modeLDRT用戶模式下把一個(gè)字裝入一個(gè)寄存器Rd←mem32[address]under user modeSTRT用戶模式下將存儲(chǔ)器中的字保存到寄存器Rd←mem32[address] ]under user modeLDRSB把一個(gè)有符號(hào)字節(jié)裝入一個(gè)寄存器Rd←sign{mem8[address]}LDRSH把一個(gè)有符號(hào)半字裝入一個(gè)寄存器Rd←sign{mem16[address]}

                                                                                        1. LDR指令

                                                                                        LDR指令用于從內(nèi)存中將一個(gè)32位的字讀取到目標(biāo)寄存器。

                                                                                          1. 指令的語法格式:




                                                                                          LDR{<cond>} <Rd>,<addr_mode>

                                                                                            1. 指令舉例:




                                                                                            LDR R1,[R0,#0x12] ;將R0+12地址處的數(shù)據(jù)讀出,保存到R1中(R0的值不變)

                                                                                            LDR R1,[R0] ;將R0地址處的數(shù)據(jù)讀出,保存到R1中(零偏移)

                                                                                            LDR R1,[R0,R2] ;將R0+R2地址的數(shù)據(jù)讀出,保存到R1中(R0的值不變)

                                                                                            LDR R1,[R0,R2,LSL #2] ;將R0+R2×4地址處的數(shù)據(jù)讀出,保存到R1中(R0、R2的值不變)

                                                                                            LDR Rd,label ;label為程序標(biāo)號(hào),label必須是當(dāng)前指令的-4~4KB范圍內(nèi)

                                                                                            LDR Rd,[Rn],#0x04 ;Rn的值用做傳輸數(shù)據(jù)的存儲(chǔ)地址。在數(shù)據(jù)傳送后,將偏移量0x04與Rn相加,結(jié)果寫回到Rn中。Rn不允許是R15

                                                                                            1. STR指令

                                                                                            STR指令用于將一個(gè)32位的字?jǐn)?shù)據(jù)寫入到指令中指定的內(nèi)存單元。

                                                                                              1. 指令的語法格式:




                                                                                              STR{<cond>} <Rd>,<addr_mode>

                                                                                                1. 指令舉例:LDR/STR指令用于對(duì)內(nèi)存變量的訪問、內(nèi)存緩沖區(qū)數(shù)據(jù)的訪問、查表、外圍部件的控制操作等,若使用LDR指令加載數(shù)據(jù)到PC寄存器,則實(shí)現(xiàn)程序跳轉(zhuǎn)功能,這樣也就實(shí)現(xiàn)了程序散轉(zhuǎn)。




                                                                                                1. 變量訪問。

                                                                                                NumCount .equ 0x40003000 ;定義變量NumCount

                                                                                                LDR R0,=NumCount ;使用LDR偽指令裝載NumCount的地址到R0

                                                                                                LDR R1,[R0] ;取出變量值

                                                                                                ADD R1,R1,#1 ;NumCount=NumCount+1

                                                                                                STR R1,[R0] ;保存變量

                                                                                                1. GPIO設(shè)置。

                                                                                                GPIO—BASE .equ 0xe0028000 ;定義GPIO寄存器的基地址

                                                                                                LDR R0,=GPIO—BASE

                                                                                                LDR R1,=0x00ffff00 ;將設(shè)置值放入寄存器

                                                                                                STR R1,[R0,#0x0C] ;IODIR=0x00ffff00,IOSET的地址為0xE0028004

                                                                                                1. 程序散轉(zhuǎn)。

                                                                                                MOV R2,R2,LSL #2 ;功能號(hào)乘以4,以便查表

                                                                                                LDR PC,[PC,R2] ;查表取得對(duì)應(yīng)功能子程序地址并跳轉(zhuǎn)

                                                                                                NOP

                                                                                                FUN—TAB .woRd FUN—SUB0

                                                                                                .woRd FUN—SUB1

                                                                                                .woRd FUN—SUB2

                                                                                                1. LDRB指令

                                                                                                LDRB指令根據(jù)addr_mode所確定的地址模式將一個(gè)8位字節(jié)讀取到指令中的目標(biāo)寄存器Rd。

                                                                                                指令的語法格式:

                                                                                                LDR{<cond>}B <Rd>, <addr_mode>

                                                                                                1. STRB指令

                                                                                                STRB指令從寄存器中取出指定的8位字節(jié)放入寄存器的低8位,并將寄存器的高位補(bǔ)0。指令的語法格式:

                                                                                                STR{<cond>}B <Rd>,<addr_mode>

                                                                                                1. LDRH指令

                                                                                                LDRH指令用于從內(nèi)存中將一個(gè)16位的半字讀取到目標(biāo)寄存器。

                                                                                                如果指令的內(nèi)存地址不是半字節(jié)對(duì)齊的,指令的執(zhí)行結(jié)果不可預(yù)知。

                                                                                                指令的語法格式:

                                                                                                LDR{<cond>}H <Rd>,<addr_mode>

                                                                                                1. STRH指令

                                                                                                STRH指令從寄存器中取出指定的16位半字放入寄存器的低16位,并將寄存器的高位補(bǔ)0。

                                                                                                指令的語法格式:

                                                                                                STR{<cond>}H <Rd>,<addr_mode>


                                                                                                1. 多寄存器的Load/Store內(nèi)存訪問指令

                                                                                                多寄存器的Load/Store內(nèi)存訪問指令也叫批量加載/存儲(chǔ)指令,它可以實(shí)現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元之間傳送數(shù)據(jù)。LDM用于加載多個(gè)寄存器,STM用于存儲(chǔ)多個(gè)寄存器。多寄存器的Load/Store內(nèi)存訪問指令允許一條指令傳送16個(gè)寄存器的任何子集或所有寄存器。多寄存器的Load/Store內(nèi)存訪問指令主要用于現(xiàn)場(chǎng)保護(hù)、數(shù)據(jù)復(fù)制和參數(shù)傳遞等。如表所示列出了多寄存器的Load/Store內(nèi)存訪問指令。

                                                                                                表 多寄存器的Load/Store內(nèi)存訪問指令

                                                                                                指 令作 用操 作LDM裝載多個(gè)寄存器{Rd}*N←mem32[start address+4*N]STM保存多個(gè)寄存器{Rd}*N→mem32[start address+4*N]

                                                                                                1. LDM指令

                                                                                                LDM指令將數(shù)據(jù)從連續(xù)的內(nèi)存單元中讀取到指令中指定的寄存器列表中的各寄存器中。當(dāng)PC包含在LDM指令的寄存器列表中時(shí),指令從內(nèi)存中讀取的字?jǐn)?shù)據(jù)將被作為目標(biāo)地址值,指令執(zhí)行后程序?qū)哪繕?biāo)地址處開始執(zhí)行,從而實(shí)現(xiàn)了指令的跳轉(zhuǎn)。

                                                                                                指令的語法格式:

                                                                                                LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>

                                                                                                寄存器R0~R15分別對(duì)應(yīng)于指令編碼中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,則相應(yīng)的位等于1,否則為0。LDM指令將數(shù)據(jù)從連續(xù)的內(nèi)存單元中讀取到指令中指定的寄存器列表中的各寄存器中。

                                                                                                指令的語法格式:

                                                                                                LDM{<cond>}<addressing_mode><Rn>,<registers_without_pc>

                                                                                                1. STM指令

                                                                                                STM指令將指令中寄存器列表中的各寄存器數(shù)值寫入到連續(xù)的內(nèi)存單元中。主要用于塊數(shù)據(jù)的寫入、數(shù)據(jù)棧操作及進(jìn)入子程序時(shí)保存相關(guān)寄存器的操作。

                                                                                                指令的語法格式:

                                                                                                STM{<cond>}<addressing_mode> <Rn>{!}, <registers>

                                                                                                1. 數(shù)據(jù)傳送指令應(yīng)用

                                                                                                LDM/STM批量加載/存儲(chǔ)指令可以實(shí)現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元之間傳輸數(shù)據(jù)。LDM為加載多個(gè)寄存器,STM為存儲(chǔ)多個(gè)寄存器。允許一條指令傳送16個(gè)寄存器的任何子集或所有寄存器。指令格式如下:

                                                                                                LDM{cond}<模式> Rn{!},regist{?}

                                                                                                STM{cond}<模式> Rn{!},regist{?}

                                                                                                LDM/STM的主要用途有現(xiàn)場(chǎng)保護(hù)、數(shù)據(jù)復(fù)制和參數(shù)傳遞等。其模式有8種,其中前面4種用于數(shù)據(jù)塊的傳輸,后面4種是堆棧操作,如下所示。

                                                                                                (1)IA:每次傳送后地址加4。

                                                                                                (2)IB:每次傳送前地址加4。

                                                                                                (3)DA:每次傳送后地址減4。

                                                                                                (4)DB:每次傳送前地址減4。

                                                                                                (5)FD:滿遞減堆棧。

                                                                                                (6)ED:空遞增堆棧。

                                                                                                (7)FA:滿遞增堆棧。

                                                                                                (8)EA:空遞增堆棧。

                                                                                                其中,寄存器Rn為基址寄存器,裝有傳送數(shù)據(jù)的初始地址,Rn不允許為R15;后綴“!”表示最后的地址寫回到Rn中;寄存器列表reglist可包含多于一個(gè)寄存器或寄存器范圍,使用“,”分開,如{R1,R2,R6~R9},寄存器排列由小到大排列;“?”后綴不允許在用戶模式下使用,只能在系統(tǒng)模式下使用。若在LDM指令用寄存器列表中包含有PC時(shí)使用,那么除了正常的多寄存器傳送外,將SPSR復(fù)制到CPSR中,這可用于異常處理返回;使用“?”后綴進(jìn)行數(shù)據(jù)傳送且寄存器列表不包含PC時(shí),加載/存儲(chǔ)的是用戶模式寄存器,而不是當(dāng)前模式寄存器。

                                                                                                LDMIA R0!,{R3~R9} ;加載R0指向的地址上的多字?jǐn)?shù)據(jù),保存到R3~R9中,R0值更新

                                                                                                STMIA R1!,{R3~R9} ;將R3~R9的數(shù)據(jù)存儲(chǔ)到R1指向的地址上,R1值更新

                                                                                                STMFD SP!,{R0~R7,LR} ;現(xiàn)場(chǎng)保存,將R0~R7、LR入棧

                                                                                                LDMFD SP!,{R0~R7,PC}? ;恢復(fù)現(xiàn)場(chǎng),異常處理返回

                                                                                                在進(jìn)行數(shù)據(jù)復(fù)制時(shí),先設(shè)置好源數(shù)據(jù)指針,然后使用塊復(fù)制尋址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB進(jìn)行讀取和存儲(chǔ)。而進(jìn)行堆棧操作時(shí),則要先設(shè)置堆棧指針,一般使用SP然后使用堆棧尋址指令STMFD/LDMFD、STMED/LDMED、STMEA/LDMEA實(shí)現(xiàn)堆棧操作。數(shù)據(jù)是存儲(chǔ)在基址寄存器的地址之上還是之下,地址是存儲(chǔ)第一個(gè)值之前還是之后、增加還是減少,如表所示。

                                                                                                向 上 生 長(zhǎng)向 下 生 長(zhǎng)滿空滿空增加之前STMIBLDMIBSTMFALDMED之后STMIALDMIASTMEALDMFD增加之前LDMDBSTMDBLDMEASTMFD之后LDMDASTMDALDMFASTMED

                                                                                                【舉例】 使用LDM/STM進(jìn)行數(shù)據(jù)復(fù)制。

                                                                                                LDR R0,=SrcData ;設(shè)置源數(shù)據(jù)地址

                                                                                                LDR R1,=DstData ;設(shè)置目標(biāo)地址

                                                                                                LDMIA R0,{R2~R9} ;加載8字?jǐn)?shù)據(jù)到寄存器R2~R9

                                                                                                STMIA R1,{R2~R9} ;存儲(chǔ)寄存器R2~R9到目標(biāo)地址

                                                                                                【舉例】 使用LDM/STM進(jìn)行現(xiàn)場(chǎng)寄存器保護(hù),常在子程序或異常處理使用。

                                                                                                SENDBYTE:

                                                                                                STMFD SP!,{R0~R7,LR} ;寄存器壓棧保護(hù)

                                                                                                BL DELAY ;調(diào)用DELAY子程序

                                                                                                LDMFD SP!,{R0~R7,PC} ;恢復(fù)寄存器,并返回


                                                                                                1. 單數(shù)據(jù)交換指令

                                                                                                交換指令是Load/Store指令的一種特例,它把一個(gè)寄存器單元的內(nèi)容與寄存器內(nèi)容交換。交換指令是一個(gè)原子操作(Atomic Operation),也就是說,在連續(xù)的總線操作中讀/寫一個(gè)存儲(chǔ)單元,在操作期間阻止其他任何指令對(duì)該存儲(chǔ)單元的讀/寫。交換指令如表所示。

                                                                                                指 令作 用操 作SWP字交換tmp=men32[Rn]mem32[Rn]=RmRd=tmpSWPB字節(jié)交換tmp=men8[Rn]mem8[Rn]=RmRd=tmp

                                                                                                1. SWP字交換指令

                                                                                                SWP指令用于將內(nèi)存中的一個(gè)字單元和一個(gè)指定寄存器的值相交換。操作過程如下:假設(shè)內(nèi)存單元地址存放在寄存器<Rn>中,指令將<Rn>中的數(shù)據(jù)讀取到目的寄存器Rd中,同時(shí)將另一個(gè)寄存器<Rm>的內(nèi)容寫入到該內(nèi)存單元中。

                                                                                                當(dāng)<Rd>和<Rm>為同一個(gè)寄存器時(shí),指令交換該寄存器和內(nèi)存單元的內(nèi)容。

                                                                                                指令的語法格式:

                                                                                                SWP{<cond>} <Rd>,<Rm>,[<Rn>]

                                                                                                1. SWPB字節(jié)交換指令

                                                                                                SWPB指令用于將內(nèi)存中的一個(gè)字節(jié)單元和一個(gè)指定寄存器的低8位值相交換,操作過程如下:假設(shè)內(nèi)存單元地址存放在寄存器<Rn>中,指令將<Rn>中的數(shù)據(jù)讀取到目的寄存器Rd中,寄存器Rd的高24位設(shè)為0,同時(shí)將另一個(gè)寄存器<Rm>的低8位內(nèi)容寫入到該內(nèi)存字節(jié)單元中。當(dāng)<Rd>和<Rm>為同一個(gè)寄存器時(shí),指令交換該寄存器低8位內(nèi)容和內(nèi)存字節(jié)單元的內(nèi)容。

                                                                                                指令的語法格式:

                                                                                                SWP{<cond>}B <Rd>,<Rm>,[<Rn>]

                                                                                                1. 交換指令SWP應(yīng)用

                                                                                                SWP指令用于將一個(gè)內(nèi)存單元(該單元地址放在寄存器Rn中)的內(nèi)容讀取到一個(gè)寄存器Rd中,同時(shí)將另一個(gè)寄存器Rm的內(nèi)容寫到該內(nèi)存單元中,使用SWP可實(shí)現(xiàn)信號(hào)量操作。

                                                                                                指令的語法格式:

                                                                                                SWP{cond}B Rd,Rm,[Rn]

                                                                                                其中,B為可選后綴,若有B,則交換字節(jié);否則交換32位字。Rd為目的寄存器,存儲(chǔ)從存儲(chǔ)器中加載的數(shù)據(jù),同時(shí),Rm中的數(shù)據(jù)將會(huì)被存儲(chǔ)到存儲(chǔ)器中。若Rm與Rn相同,則為寄存器與存儲(chǔ)器內(nèi)容進(jìn)行交換。Rn為要進(jìn)行數(shù)據(jù)交換的存儲(chǔ)器地址,Rn不能與Rd和Rm相同。

                                                                                                SWP指令舉例:

                                                                                                SWP R1,R1,[R0] ;將R1的內(nèi)容與R0指向的存儲(chǔ)單元內(nèi)容進(jìn)行交換

                                                                                                SWPB R1,R2,[R0] ;將R0指向的存儲(chǔ)單元內(nèi)容讀取一字節(jié)數(shù)據(jù)到R1中(高24位清零), 并將R2的內(nèi)容 寫入到該內(nèi)存單元中(最低字節(jié)有效),使用SWP指令可以方便地進(jìn)行信號(hào)量操作

                                                                                                12C_SEM .equ 0x40003000

                                                                                                12C_SEM_WAIT:

                                                                                                MOV R0,#0

                                                                                                LDR R0,=12C_SEM

                                                                                                SWP R1,R1,[R0] ;取出信號(hào)量,并將其設(shè)為0

                                                                                                CMP R1,#0 ;判斷是否有信號(hào)

                                                                                                BEQ 12C_SEM_WAIT ;若沒有信號(hào)則等待

                                                                                                跳轉(zhuǎn)指令

                                                                                                跳轉(zhuǎn)(B)和跳轉(zhuǎn)連接(BL)指令是改變指令執(zhí)行順序的標(biāo)準(zhǔn)方式。ARM一般按照字地址順序執(zhí)行指令,需要時(shí)使用條件執(zhí)行跳過某段指令。只要程序必須偏離順序執(zhí)行,就要使用控制流指令來修改程序計(jì)數(shù)器。盡管在特定情況下還有其他幾種方式實(shí)現(xiàn)這個(gè)目的,但轉(zhuǎn)移和轉(zhuǎn)移連接指令是標(biāo)準(zhǔn)的方式。跳轉(zhuǎn)指令改變程序的執(zhí)行流程或者調(diào)用子程序。這種指令使得一個(gè)程序可以使用子程序、if-then-else結(jié)構(gòu)及循環(huán)。執(zhí)行流程的改變迫使程序計(jì)數(shù)器(PC)指向一個(gè)新的地址,ARMv5架構(gòu)指令集包含的跳轉(zhuǎn)指令如表所示。

                                                                                                助 記 符說 明操 作B跳轉(zhuǎn)指令pc←labelBL帶返回的連接跳轉(zhuǎn)pc←label(lr←BL后面的第一條指令)BX跳轉(zhuǎn)并切換狀態(tài)pc←Rm&0xfffffffe, T←Rm&1BLX帶返回的跳轉(zhuǎn)并切換狀態(tài)pc←lable, T←1pc←Rm&0xfffffffe, T←Rm&1lr←BL后面的第一條指令

                                                                                                另一種實(shí)現(xiàn)指令跳轉(zhuǎn)的方式是通過直接向PC寄存器中寫入目標(biāo)地址值,實(shí)現(xiàn)在4GB地址空間中任意跳轉(zhuǎn),這種跳轉(zhuǎn)指令又稱為長(zhǎng)跳轉(zhuǎn)。如果在長(zhǎng)跳轉(zhuǎn)指令之前使用“MOV LR”或“MOV PC”等指令,可以保存將來返回的地址值,也就實(shí)現(xiàn)了在4GB的地址空間中的子程序調(diào)用。

                                                                                                1. 跳轉(zhuǎn)指令B及帶連接的跳轉(zhuǎn)指令BL

                                                                                                跳轉(zhuǎn)指令B使程序跳轉(zhuǎn)到指定的地址執(zhí)行程序。帶連接的跳轉(zhuǎn)指令BL將下一條指令的地址復(fù)制到R14(即返回地址連接寄存器LR)寄存器中,然后跳轉(zhuǎn)到指定地址運(yùn)行程序。需要注意的是,這兩條指令和目標(biāo)地址處的指令都要屬于ARM指令集。兩條指令都可以根據(jù)CPSR中的條件標(biāo)志位的值決定指令是否執(zhí)行。

                                                                                                1. 指令的語法格式:

                                                                                                B{L}{<cond>} <target_address>

                                                                                                BL指令用于實(shí)現(xiàn)子程序調(diào)用。子程序的返回可以通過將LR寄存器的值復(fù)制到PC寄存器來實(shí)現(xiàn)。下面3種指令可以實(shí)現(xiàn)子程序返回。

                                                                                                1. BX R14(如果體系結(jié)構(gòu)支持BX指令)。

                                                                                                2. MOV PC,R14。

                                                                                                3. 當(dāng)子程序在入口處使用了壓棧指令:

                                                                                                STMFD R13!,{<registers>,R14}

                                                                                                可以使用指令:

                                                                                                LDMFD R13!,{<registers>,PC}

                                                                                                將子程序返回地址放入PC中。

                                                                                                ARM匯編器通過以下步驟計(jì)算指令編碼中的signed_immed_24。

                                                                                                1. 將PC寄存器的值作為本跳轉(zhuǎn)指令的基地址值。

                                                                                                2. 從跳轉(zhuǎn)的目標(biāo)地址中減去上面所說的跳轉(zhuǎn)的基地址,生成字節(jié)偏移量。由于ARM指令是字對(duì)齊的,該字節(jié)偏移量為4的倍數(shù)。

                                                                                                3. 當(dāng)上面生成的字節(jié)偏移量超過?33 554 432~+33 554 430時(shí),不同的匯編器使用不同的代碼產(chǎn)生策略。否則,將指令編碼字中的signed_immed_24設(shè)置成上述字節(jié)偏移量的bits[25:2]。

                                                                                                4. 程序舉例:

                                                                                                5. 程序跳轉(zhuǎn)到LABLE標(biāo)號(hào)處。

                                                                                                B LABLE ;

                                                                                                ADD R1,R2,#4

                                                                                                ADD R3,R2,#8

                                                                                                SUB R3,R3,R1

                                                                                                LABLE:

                                                                                                SUB R1,R2,#8

                                                                                                1. 跳轉(zhuǎn)到絕對(duì)地址0x1234處。

                                                                                                B 0x1234

                                                                                                1. 跳轉(zhuǎn)到子程序func處執(zhí)行,同時(shí)將當(dāng)前PC值保存到LR中。

                                                                                                BL func

                                                                                                1. 條件跳轉(zhuǎn):當(dāng)CPSR寄存器中的C條件標(biāo)志位為1時(shí),程序跳轉(zhuǎn)到標(biāo)號(hào)LABLE處執(zhí)行。

                                                                                                BCC LABLE

                                                                                                1. 通過跳轉(zhuǎn)指令建立一個(gè)無限循環(huán)。

                                                                                                LOOP:

                                                                                                ADD R1,R2,#4

                                                                                                ADD R3,R2,#8

                                                                                                SUB R3,R3,R1

                                                                                                B LOOP

                                                                                                1. 通過使用跳轉(zhuǎn)使程序體循環(huán)10次。

                                                                                                MOV R0,#10

                                                                                                LOOP:

                                                                                                SUBS R0,#1

                                                                                                BNE LOOP

                                                                                                1. 條件子程序調(diào)用示例。

                                                                                                CMP R0,#5 ;如果R0<5

                                                                                                BLLT SUB1 ;則調(diào)用

                                                                                                BLGE SUB2 ;否則調(diào)用SUB2

                                                                                                1. 帶狀態(tài)切換的跳轉(zhuǎn)指令BX

                                                                                                帶狀態(tài)切換的跳轉(zhuǎn)指令(BX)使程序跳轉(zhuǎn)到指令中指定的參數(shù)Rm指定的地址執(zhí)行程序,Rm的第0位復(fù)制到CPSR中T位,bit[31∶1]移入PC。若Rm的bit[0]為1,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T置位,即把目標(biāo)地址的代碼解釋為Thumb代碼;若Rm的位bit[0]為0,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志位T復(fù)位,即把目標(biāo)地址代碼解釋為ARM代碼。

                                                                                                  1. 指令的語法格式:




                                                                                                  BX{<cond>} <Rm>

                                                                                                  1. 當(dāng)Rm[1∶0]=0b10時(shí),指令的執(zhí)行結(jié)果不可預(yù)知。因?yàn)樵贏RM狀態(tài)下,指令是4字節(jié)對(duì)齊的。

                                                                                                  2. PC可以作為Rm寄存器使用,但這種用法不推薦使用。當(dāng)PC作為<Rm>使用時(shí),指令“BX PC”將程序跳轉(zhuǎn)到當(dāng)前指令下面第二條指令處執(zhí)行。雖然這樣跳轉(zhuǎn)可以實(shí)現(xiàn),但最好使用下面的指令完成這種跳轉(zhuǎn)。

                                                                                                  MOV PC, PC

                                                                                                  ADD PC, PC, #0

                                                                                                    1. 指令舉例:




                                                                                                    1. 轉(zhuǎn)移到R0中的地址,如果R0[0]=1,則進(jìn)入Thumb狀態(tài)。

                                                                                                    BX R0;

                                                                                                    1. 跳轉(zhuǎn)到R0指定的地址,并根據(jù)R0的最低位來切換處理器狀態(tài)。

                                                                                                    ADRL R0,ThumbFun+1 ;

                                                                                                    BX R0;

                                                                                                    1. 帶連接和狀態(tài)切換的連接跳轉(zhuǎn)指令BLX

                                                                                                    帶連接和狀態(tài)切換的跳轉(zhuǎn)指令(Branch with Link Exchange,BLX)使用標(biāo)號(hào),用于使程序跳轉(zhuǎn)到Thumb狀態(tài)或從Thumb狀態(tài)返回。該指令為無條件執(zhí)行指令,并用分支寄存器的最低位來更新CPSR中的T位,將返回地址寫入到連接寄存器LR中。

                                                                                                      1. 語法格式:




                                                                                                      BLX <target_add>

                                                                                                      其中,<target_add>為指令的跳轉(zhuǎn)目標(biāo)地址。該地址根據(jù)以下規(guī)則計(jì)算。

                                                                                                      1. 將指令中指定的24位偏移量進(jìn)行符號(hào)擴(kuò)展,形成32位立即數(shù)。

                                                                                                      2. 將結(jié)果左移兩位。

                                                                                                      3. 位H(bit[24])加到結(jié)果地址的第一位(bit[1])。

                                                                                                      4. 將結(jié)果累加進(jìn)程序計(jì)數(shù)器(PC)中。

                                                                                                      計(jì)算偏移量的工作一般由ARM匯編器來完成。這種形式的跳轉(zhuǎn)指令只能實(shí)現(xiàn)?32~32MB空間的跳轉(zhuǎn)。左移兩位形成字偏移量,然后將其累加進(jìn)程序計(jì)數(shù)器(PC)中。這時(shí),程序計(jì)數(shù)器的內(nèi)容為BX指令地址加8字節(jié)。位H(bit[24])也加到結(jié)果地址的第一位(bit[1]),使目標(biāo)地址成為半字地址,以執(zhí)行接下來的Thumb指令。計(jì)算偏移量的工作一般由ARM匯編器來完成。這種形式的跳轉(zhuǎn)指令只能實(shí)現(xiàn)?32~32MB空間的跳轉(zhuǎn)。

                                                                                                        1. 指令的使用




                                                                                                        1. 從Thumb狀態(tài)返回到ARM狀態(tài),使用BX指令。

                                                                                                        BX R14

                                                                                                        1. 可以在子程序的入口和出口增加棧操作指令。

                                                                                                        PUSH {<registers>,R14}

                                                                                                        POP {<registers>,PC}



                                                                                                        硬件平臺(tái):華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)

                                                                                                        部分開發(fā)教程下載:加QQ群483143191,群文件里有。

                                                                                                        部分視頻課程收看:華清遠(yuǎn)見研發(fā)中心的個(gè)人空間_嗶哩嗶哩_Bilibili

                                                                                                        淘寶購買鏈接:item.taobao.com/item.ht

                                                                                                        手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?


                                                                                                        ARM裸機(jī)開發(fā)篇2:ARM微處理器指令系統(tǒng)(一)的評(píng)論 (共 條)

                                                                                                        分享到微博請(qǐng)遵守國(guó)家法律
                                                                                                        清河县| 奉节县| 卢氏县| 丰镇市| 昆明市| 贵德县| 英吉沙县| 柞水县| 廉江市| 神农架林区| 绩溪县| 阳谷县| 巴林右旗| 巴马| 柘城县| 六安市| 无为县| 敦化市| 延吉市| 阜新市| 宁乡县| 尼木县| 临安市| 扶风县| 温州市| 新竹县| 武川县| 姚安县| 双鸭山市| 马尔康县| 敦化市| 马鞍山市| 清苑县| 始兴县| 寿阳县| 花莲县| 黑龙江省| 江口县| 囊谦县| 南郑县| 霍州市|