<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM匯編指令ARM尋址方式、匯編指令、偽指令

          ARM匯編指令ARM尋址方式、匯編指令、偽指令

          作者: 時間:2016-11-20 來源:網(wǎng)絡 收藏
          1、尋址方式

          所謂尋址方式就是:處理器根據(jù)指令中給出的地址信息來尋找物理地址的方法。

          本文引用地址:http://www.ex-cimer.com/article/201611/318766.htm

          1)立即尋址

          立即尋址也叫立即數(shù)尋址,這是一種特殊的尋址方式,操作數(shù)本身就是在指令中給出的。

          只要取出指令也就是取得了操作數(shù),這個操作數(shù)被稱為立即數(shù),對應的尋址方式也就叫做立即數(shù)尋址。

          例如:

          △:ADD R0,R0,#1;R0<-R0+1

          △:ADD R0,R0,#0X3F;R0<-R0+0X3F

          2)寄存器尋址

          寄存器尋址就是利用寄存器中的數(shù)值作為操作數(shù),這種尋址方式是各類微處理器經(jīng)常使用的一種方式,

          也是一種執(zhí)行效率較高的尋址方式。

          例程:

          ADD R0,R1,R2;R0<-R1+R2

          3)寄存器間接尋址

          寄存器間接尋址就是以寄存器中的值作為操作數(shù)的地址,而操作數(shù)本身就放在存儲器中。

          例如:

          ADD R0,R1,[R2];R0<-R1+[R2]

          LDRR0,[R1];R0<-[R1]

          4)基址變址尋址

          基址變址尋址就是將寄存器(該寄存器一般稱為基址寄存器)的內(nèi)容與指令中給出的地址偏移量相加,

          從而得到一個操作數(shù)的有效地址:

          例如:

          LDR R0,[R1,#4];R0<-[R1+4]

          LDR R0,[R1,#4]!;R0<-[R1+4]、R1<-R1+4

          LDR R0,[R1],#4;R0<-[R1+4]、R1<-R1+4

          4)多寄存器尋址

          采用多寄存器尋址方式,一條指令可以完成多個寄存器值的傳送。

          這種尋址方式可以用一條指令完成傳送最多16個通用寄存器的值。

          例如:

          LDMIA R0,{R1,R2,R3,R4};R1<-[R0]

          ;R2<-[R0+4]

          ;R3<-[R0+8]

          ;R4<-[R0+12]

          注意:該指令的后綴IA表示在每次執(zhí)行完加載、存儲操作后,R0按字長度增加,因此,指令可以將

          連續(xù)存儲單元的值送到R1~R4。

          5)相對尋址

          與基址變址尋址方式相類似,相對尋址以程序計數(shù)器PC的當前值為基地址,指令中的地址標號作為偏移量,

          將兩者相加之后得到的操作數(shù)的有效地址。

          例如:

          BL NEX

          6)堆棧尋址

          T堆棧是一種數(shù)據(jù)結(jié)構(gòu),按先進后出(First In Last Out,FILO)的方式工作,使用一個稱作為

          堆棧指針的專用寄存器指示當前的操作位置,堆棧指針總是指向棧頂。

          遞增堆棧:向高地址方向生長

          遞減堆棧:向低地址方向生長

          滿堆棧:堆棧指針指向最后壓入堆棧的有效數(shù)據(jù)項

          空堆棧:堆棧指針指向下一個要放入數(shù)據(jù)的空位置

          2、ARM指令

          1)跳轉(zhuǎn)指令

          跳轉(zhuǎn)指令用于實現(xiàn)程序流程的跳轉(zhuǎn),在ARM程序中有兩種方法可以實現(xiàn)程序流程的跳轉(zhuǎn):

          △:使用專門的跳轉(zhuǎn)指令。

          △:直接向程序計數(shù)器PC寫入跳轉(zhuǎn)地址值,通過向程序計數(shù)器PC寫入跳轉(zhuǎn)地址值,可以實現(xiàn)在4GB的

          地址空間中的任意跳轉(zhuǎn),在跳轉(zhuǎn)之前結(jié)合使用MOV LR,PC

          等類似的指令,可以保存將來的返回地址值,從而實現(xiàn)在4GB連續(xù)的線性地址空間的子程序調(diào)用。

          在ARM指令集中的跳轉(zhuǎn)指令可以完成從當前指令向前或者向后的32MB的地址空間的跳轉(zhuǎn),包括以下四條指令:

          △:B跳轉(zhuǎn)指令

          △:BL帶返回的跳轉(zhuǎn)至靈

          △:BLX帶返回和狀態(tài)切換的跳轉(zhuǎn)指令

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

          ①、B指令:

          B{條件}目標地址

          B指令是最簡單的跳轉(zhuǎn)指令。一旦遇到一個B指令,ARM處理器將立即跳轉(zhuǎn)到給定的目標地址,從那里開始繼續(xù)執(zhí)行。

          例如:

          CMP R1,#0

          BEQ LABEL;當CPSR寄存器中的Z條件碼置位時,程序跳轉(zhuǎn)到標號LABEL處執(zhí)行

          順便把指令的條件貼出來:


          ②、BL指令:

          BL{條件}目標地址

          BL是另一個跳轉(zhuǎn)指令,但跳轉(zhuǎn)之前,會在寄存器R14(LR)中保存PC當前值,

          因此,可以通過將LR的內(nèi)容重新加載到PC中,來返回到跳轉(zhuǎn)指令之后的那個指令處執(zhí)行。

          該指令是實現(xiàn)子程序調(diào)用的一個基本但常用的手段。

          ③、BLX指令

          BLX 目標地址

          BLX指令從ARM指令集跳轉(zhuǎn)到指令中所指定的目標地址,并將處理器的工作狀態(tài)有ARM狀態(tài)切換到Thumb狀態(tài),

          該指令同時將PC的當前內(nèi)容保存到R14中。

          因此,當子程序使用Thumb指令時,而調(diào)用者使用ARM指令,可以通過BLX指令實現(xiàn)子程序的調(diào)用和處理器

          工作狀態(tài)的切換。

          同時,子程序返回可以通過寄存器R14值到PC中來完成返回。

          ④、BX指令

          BX{條件} 目標地址

          BX指令跳轉(zhuǎn)到指令中指定的目標地址,目標地址的指令既可以是ARM指令,也可以是Thumb指令。

          2、數(shù)據(jù)處理指令

          數(shù)據(jù)處理指令可以分為數(shù)據(jù)傳送指令、算術(shù)邏輯運算指令和比較指令等。

          數(shù)據(jù)傳送指令用于在寄存器和寄存器之間(這里一定要看清楚是寄存器與寄存器!?。。┻M行數(shù)據(jù)的雙向傳輸。

          算術(shù)邏輯運算指令完成常用的算術(shù)和邏輯的運算,該指令不但將運算結(jié)果博愛存在目的寄存器中,同時更新CPSR中的相應條件標志位。

          1)MOV指令

          MOC{條件}{S}目的寄存器,原操作數(shù)(都是寄存器?。。。?/p>

          MOV指令完成從一個寄存器、被移位的寄存器加載到目的寄存器。

          其中S選項決定指令的操作是否影響CPSR中條件標志位的值,當沒有S時指令不更新CPSR中條件標志位的值。

          例程:

          MOV R1,R0

          MOV PC,R14

          MOV R1,R0,LSL #3

          2)MVN指令

          MVN{條件}{S}目的寄存器,原操作數(shù)

          MVN指令完成從另一個寄存器、被移位的寄存器、或?qū)⒁粋€立即數(shù)加載到目的寄存器。

          與MOV指令不同之處是在傳送之前按位取反了,既把一個取反的值傳送給目的寄存器中。

          其中S決定指令的操作是否影響CPSR中條件標識為的值,當沒有S時指令不更新CPSR中條件標志位的值。

          例程:

          MVNR0,#0XFF

          3)CMP指令

          CMP{條件} 操作數(shù)1,操作數(shù)2

          CMP指令用于把一個寄存器內(nèi)容和另一個寄存器的內(nèi)容或者立即數(shù)進行比較,同時更新CPSR中

          條件標志位的值。

          該指令進行一次減法運算,但是不保存結(jié)果,只更改條件標志位(其中指令條件上邊的圖片~~)~~

          例如:

          CMP R1,RO

          CMP R1,#100;將寄存器R1中的值與立即數(shù)100相減,并根據(jù)結(jié)果設置CPSR的標志位

          4)TST指令

          TST{條件}操作數(shù)1,操作數(shù)2

          TST指令用于把一個寄存器的內(nèi)容和另一個寄存器的內(nèi)容或者立即數(shù)按位的與運算。

          并根據(jù)結(jié)果更新CPSR中條件標志位的值。

          操作數(shù)1是要測試的數(shù)據(jù),而操作數(shù)2是一個位掩碼,根據(jù)測試結(jié)果設置相應的標志位。

          例程:

          TST R1,#%1;用于測試在寄存器R1中是否設置了最低位(%表示二進制數(shù))。

          5)ADD指令

          ADD{條件}{S} 目的寄存器,操作數(shù)1,操作數(shù)2

          ADD指令用于把兩個操作數(shù)相加,并將結(jié)果存放到目的寄存器中。

          操作數(shù)1一概是一個寄存器,操作數(shù)2可以是一個寄存器,被一位的寄存器,或者一個立即數(shù)。

          例程:

          ADD R0,R1,R2

          ADD R0,R2,R3,LSL#1

          6)SUB指令

          不想說~~因為跟ADD指令一模一樣,只是一個加一個減~~

          7)AND指令

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

          AND指令用于在兩個操作數(shù)上進行邏輯與運算,并肩結(jié)果放置在目的寄存器。

          格式跟ADD一樣。

          例程:

          AND R0,R0,#3;該指令保持R0的0、1位,其余位清零

          8)ORR指令

          按位或,格式跟AND指令一樣~~

          功能:常用于設置操作數(shù)1的某些位。

          9)BIC指令

          BIC{條件}{S} Rd,Rn,operand2

          BIC指令用于清除Rn中的某些位,并把結(jié)果存放在Rd中,操作數(shù)operand2為32位的掩碼,如果

          掩碼中設置了某一位為1,則清除這一位。

          例程:

          BIC R0,R0,#11;將R0的0,1,3位清零,其余位不變。

          10)MUL指令

          MUL{條件}{S}目的寄存器,操作數(shù)1,操作數(shù)2

          其中操作數(shù)1和操作數(shù)2均為32位的有符號數(shù)或者無符號數(shù)。

          11)MRS指令(程序狀態(tài)寄存器訪問指令)

          MRS{條件} 通用寄存器,程序狀態(tài)寄存器(CPSR或SPSR)

          MRS指令用于將程序狀態(tài)寄存器的內(nèi)容傳送到通用寄存器中。

          注意:

          該指令用于一下情況:

          a、當需要改變程序狀態(tài)寄存器時,可以用MRS將程序狀態(tài)寄存器的內(nèi)容讀入通用寄存器,

          修改后再寫回程序狀態(tài)寄存器。

          b、當在異常處理或進程切換時,需要保存程序狀態(tài)寄存器的值,可以先用該指令讀出程序狀態(tài)寄存器的值,然后保存。

          12)MSR指令(與MRS相對應)

          MSR{條件} 程序轉(zhuǎn)臺寄存器(CPSR或者SPSR)_<域>,操作數(shù)

          MSR指令用于將操作數(shù)的內(nèi)容傳送到程序狀態(tài)寄存器的特定域中,其中,操作數(shù)可以為通用寄存器或立即數(shù)。

          <域>用于設置程序狀態(tài)寄存器中需要操作的位,32位的程序狀態(tài)寄存器可分為4個域:

          位[31:24]為條件標志位域,用f表示

          位[23:16]為狀態(tài)位域,用s表示

          位[15:8]為擴展為域,用x表示

          位[7:0]為控制位域,用c表示

          該指令通常用于或者改變程序轉(zhuǎn)臺寄存器的內(nèi)容,在使用時,一般要在MSR指令中指明將要操作的域。

          例程:

          MSR CPSR_C,RO;傳送R0的內(nèi)容到SPSR,但是僅僅修改CPSR中的位控制域

          13)LDR指令(加載指令)

          首先介紹一下加載/存儲指令:

          ARM微處理器支持加載/存儲指令用于在寄存器和存儲器之間傳送數(shù)據(jù),加載指令用于將存儲器中的數(shù)據(jù)傳送到寄存器,存儲指令則完成相反的操作。

          LDR{條件} 目的寄存器,<存儲器地址>

          LDR指令用于從存儲器中將一個32位的數(shù)據(jù)傳送到目的寄存器中。

          該指令通常用于從存儲器中讀取32位的子數(shù)據(jù)到通用寄存器,然后對數(shù)據(jù)進行處理。

          14)LDRB指令

          格式通LDR指令一樣!

          LDRB指令用于從存儲器中將一個8位的字節(jié)數(shù)據(jù)傳送到目的寄存器中,同時將寄存器的高24位清零。

          15)LDRH指令

          LDRH指令用于從存儲器中將一個16位的半字數(shù)據(jù)傳送到目的寄存器中,同時將寄存器中的高16位清零。

          16)STR指令(存儲指令)

          STR{條件} 源寄存器,<存儲器地址>

          STR指令用于從源寄存器中將一個32位的字數(shù)據(jù)傳送到存儲器中。

          17)批量加載/存儲指令-LDM/STM

          ARM微處理器所支持的批量數(shù)據(jù)加載/存儲指令可以一次在一片連續(xù)的存儲器單元和多個寄存器之間傳送數(shù)據(jù),

          批量加載指令用于將一片連續(xù)的存儲器中的數(shù)據(jù)傳送到多個寄存器,批量數(shù)據(jù)存儲指令則完成相反的操作。

          LDM{條件}{類型} 基址寄存器{!},寄存器列表

          LDM(或STM)指令用于從由基址寄存器所指示的一片連續(xù)存儲器到寄存器列表所指示的多個寄存器之間

          傳送數(shù)據(jù),該指令的常見用途是將多個寄存器的內(nèi)容入?;虺鰲?。

          類型:

          IA:每次傳送后地址加1

          IB:每次傳送前地址加1

          DA:每次傳送后地址減1

          DB:每次傳送前地址減1

          FD:滿遞減堆棧

          ED:空遞減堆棧

          FA:滿遞增堆棧

          EA:空遞增堆棧

          {!}:

          為可選后綴,若選用該后綴,則當數(shù)據(jù)傳送完畢之后,將最后的地址寫入基址寄存器,否則基址寄存器的內(nèi)容不改變。基址寄存器不允許為R15,寄存器列表可以為R0~R15的任意組合。

          {^}:

          為可選后綴,當指令為LDM且寄存器列表中包含R15,選用該后綴時表示:除了正常的數(shù)據(jù)纏訟之外,還將SPSR到CPSR。

          例程:

          STM R13!,{R0,R4-R12,LR};將寄存器列表中的寄存器(R0,R4-R12,R13)存入堆棧

          LDMFD R13!,{R0,R4-R12,PC};將堆棧內(nèi)容恢復到寄存器(R0,R4-R12,LR)

          18)SWP指令

          SWP{條件} 目的寄存器,源寄存器1,[源寄存器2]

          SWP指令用于將源寄存器2所指向的存儲器中的字數(shù)據(jù)傳送到目的寄存器中,同時將源寄存器1中的子數(shù)據(jù)傳送到源寄存器2所指向的存儲器中。

          顯然,當源寄存器1和目的寄存器為同一個寄存器時,指令交換該寄存器和存儲器的內(nèi)容。

          例程:

          SWP R0,R0,[R1]

          19)移位指令

          ARM微處理器所支持數(shù)據(jù)的移位操作~~

          移位操作在ARM指令集中不作為單獨的指令使用,他只能作為指令格式中是一個字段,在匯編語言中表示為指令中的選項。

          移位操作包括如下6中:ASL和LSL是等價的!

          △:LSL邏輯左移(按操作數(shù)所指定的數(shù)據(jù)向左移位,低位用0來補。其中,操作數(shù)可以是通用寄存器或者立即數(shù)(0~31)。)
          △:ASL算術(shù)左移
          △:LSR邏輯右移
          △:ASR算術(shù)右移
          △:ROR循環(huán)右移(注意:操作數(shù)可以是通用寄存器,也可以是立即數(shù)(0~31)。)
          20)異常產(chǎn)生指令(暫時用不到~~所以不寫了~~)
          ARM微處理器所支持的異常指令有兩條:
          SWI軟件中斷指令
          BKPT斷點中斷指令
          3、ARM偽指令
          在ARM匯編語言程序里,有一些特殊指令助記符,這些助記符與指令系統(tǒng)的助記符不同,沒有
          相對應的操作碼,通常稱這些特殊指令助記符為偽指令,他們所完成的操作稱為偽操作。
          偽操作在源程序中的作用是為了完成匯編程序做各種準備工作的,這些偽指令僅在匯編過程中起作用,一旦
          匯編結(jié)束,偽指令的是名也就完成了。
          在ARM的匯編程序中,有如下幾種偽指令:
          符號定義偽指令、數(shù)據(jù)定義偽指令、匯編控制偽指令、宏指令以及其他偽指令。
          1)符號定義偽指令
          符號定義偽指令用于定義ARM匯編程序中的變量、對變量賦值以及定義寄存器的別名等操作。
          常見的有:
          △:定義全局變量的GBLA、GBLL和GBLS
          △:定義局部變量的LCAL、LCLL和LCLS
          △:對變量賦值的SETA、SETL、SETS
          △:為通用寄存器列表定義名稱的RLIST
          ①、GBLA/GBLL/GBLS
          格式:
          GBLA/GBLL/GBLS全局變量名(在整個程序范圍內(nèi)變量名必須唯一?。。?/div>
          用于定義一個ARM程序中的全局變量,并將其初始化。
          △:GBLA:定義一個全局的數(shù)字變量,并初始化為0;
          △:GBLL:定義一個全局的邏輯變量,并初始化為F(假);
          △:GBLS:定義一個全局的字符串變量,并初始化為空;

          例程:

          GBLA TEST

          TEST SETA 0XAA

          ②、LCALL/LCLL/LCLS

          跟①是一樣一樣的~~只不過是局部變量而已!

          ③RLIST

          格式:

          名稱 RLIST {寄存器列表}

          RLIST偽指令用于對一個通用寄存器列表定義名稱,使用該偽指令定義的列表名稱可在ARM指令LDM/STM中使用。

          在LDM/STM指令中,列表中的寄存器訪問次序為根據(jù)寄存器的標號由低到高,而與列表中的寄存器排列次序無關(guān)。

          例程:

          REGLIST RLIST {R0-R5,R8,R10};將寄存器列表名稱定義為REGLIST,可以在ARM指令LDM/STM中通過該名稱訪問寄存器列表。

          2)數(shù)據(jù)定義偽指令

          數(shù)據(jù)定義偽指令一般用于為特定的數(shù)據(jù)分配存儲單元,同時可完成已分配存儲單元的初始化。

          常見的數(shù)據(jù)定義偽指令有:

          DCBDCWDCDDCFD

          DCDSDCQSPACE MAPFIELD

          ①、DCB指令

          格式:

          標號 DCB 表達式

          DCB偽指令用于分配一個連續(xù)的自己存儲單元并用偽指令中指定的表達式初始化。

          其中,表達式可以為0~255的數(shù)字或字符串。

          DCB也可以用”=“代替。

          例程:

          STR DCB "This is a test!";分配一片連續(xù)的字節(jié)存儲單元并初始化

          ②、SPACE指令

          格式:

          標號 SPACE 表達式

          SPACE偽指令用于分配一片連續(xù)的存儲區(qū)域并初始化為0。

          其中,表達式為要分配的字節(jié)數(shù)。SPACE可以用”%“代替。

          例程:

          DATASPACE SPACE 100;分配連續(xù)的100字節(jié)的存儲單元并初始化為0

          ③、MAP指令

          格式:

          MAP 表達式{,基址寄存器}

          MAP為指令用于定義一個結(jié)構(gòu)化的內(nèi)存表的首地址。

          MAP也可以用”^“代替。

          表達式可以為程序中的標號或數(shù)學表達式,基址寄存器為可選項,當基址寄存器選擇不存在時,

          表達式的值即為內(nèi)存表的首地址,當該選項存在時,內(nèi)存表的首地址為表達式的值與基址寄存器的和。

          MAP偽指令通常與FIELD偽指令配合使用來定義結(jié)構(gòu)化的內(nèi)存表。

          例程:

          MAP 0x100,R0;定義結(jié)構(gòu)化內(nèi)存表首地址的值為0x100+R0

          ④FILED指令

          通常都與MAP指令一起用。

          格式:

          標號 FIELD 表達式

          FIELD為指令用于定義一個結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域,F(xiàn)ILED也可用”#“代替。

          表達式的值為當前數(shù)據(jù)域在內(nèi)存表中所占的字節(jié)數(shù)。

          FIELD偽指令定義內(nèi)存表中的各個數(shù)據(jù)域,并可以為每個數(shù)據(jù)域指定一個標號使其他的指令

          引用。

          例程:

          MAP 0X100;定義結(jié)構(gòu)化內(nèi)存表首地址為0x100

          A FIELD 16;定義A的長度為16個字節(jié),位置位0x100

          B FIELD 32;定義B的長度誒32個字節(jié),位置位0x110

          3)匯編控制偽指令(這個東西不想寫了,用到了,一查就哦了~~寫多了也沒用多了好)

          匯編控制偽指令用于控制匯編陳旭的執(zhí)行流程,常用的匯編控制偽指令包括以下幾條:

          △:IF、ELSE、ENDIF

          △:WHILE、WEND

          △:MACRO、WEND

          △:MEXIT

          4)其它偽指令

          △:AREA

          △:ALIGN

          △:CODE16、CODE32

          △:ENTRY

          △:END

          △:EQU

          △:EXPORT(Or GLOBAL)(這個是聲明一個u且安居的標號,該標號可在其它文件引用??!和C語言一個道理~~)

          △:IMPORT

          △:EXTERN

          △:GET(Or INCLUDE)

          這里我就說下IPMORT指令吧:

          IPMORT 標號

          IMPORT偽指令用于通知編譯器要使用得標號在其他的源文件中定義,但要在當前源文件中引用。

          標號在程序中區(qū)分大小寫。

          使用實例:

          ARET Init,CODE,READONLY

          IMPORT Main;通知編譯器當前文件要引用標號Main,但Main在其它的源文件中定義的!



          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();