【匯編指令】arm指令集之但寄存器數據loadstore (加載存儲) -开发者知识库

【匯編指令】arm指令集之但寄存器數據loadstore (加載存儲) -开发者知识库,第1张

數據的傳送:

LDR              STR                   .WORD

LDRB            STRB              .BYTE

LDRH             STRH            .HALFWORD


  LDR 和STR
        加載/存儲字和無符號字節指令。使用單一數據傳送指令(STR 和LDR)來裝載和存儲單一字節或字的數據從/到內存。LDR指令用於從內存中讀取數據放入寄存器中;STR 指令用於將寄存器中的數據保存到內存。指令格式如下:
        LDR{cond}{T} Rd,<地址>;加載指定地址上的數據(字),放入Rd中
        STR{cond}{T} Rd,<地址>;存儲數據(字)到指定地址的存儲單元,要存儲的數據在Rd中
        LDR{cond}B{T} Rd,<地址>;加載字節數據,放入Rd中,即Rd最低字節有效,高24位清零
        STR{cond}B{T} Rd,<地址>;存儲字節數據,要存儲的數據在Rd,最低字節有效
        其中,T 為可選后綴,若指令有T,那么即使處理器是在特權模式下,存儲系統也將訪問看成是處理器是在用戶模式下。T在用戶模式下無效,不能與前索引偏移一起使用T。
        LDR/STR 指令尋址是非常靈活的,由兩部分組成,一部分為一個基址寄存器,可以為任一個通用寄存器,另一部分為一個地址偏移量。地址偏移量有以下3種格式:
        (1) 立即數。立即數可以是一個無符號數值,這個數據可以加到基址寄存器,也可以從基址寄存器中減去這個數值。指令舉例如下:
        LDR R1,[R0,#0x12] ;將R0 0x12 地址處的數據讀出,保存到R1中(R0 的值不變)
        LDR R1,[R0,#-0x12];將R0-0x12 地址處的數據讀出,保存到R1中(R0 的值不變)
        LDR R1,[R0] ;將R0 地址處的數據讀出,保存到R1 中(零偏移)
        (2)寄存器。寄存器中的數值可以加到基址寄存器,也可以從基址寄存器中減去這個數值。指令舉例值。指令舉例如下:
        LDR R1,[R0,R2] ;將R0 R2 地址的數據計讀出,保存到R1中(R0 的值不變)
        LDR R1,[R0,-R2] ;將R0-R2 地址處的數據計讀出,保存到R1中(R0 的值不變)
        (3)寄存器及移位常數。寄存器移位后的值可以加到基址寄存器,也可以從基址寄存器中減去這個數值。指令舉例如下:
        LDR R1,[R0,R2,LSL #2] ;將R0 R2*4地址處的數據讀出,保存到R1中(R0,R2的值不變)
        LDR R1,[R0,-R2,LSL #2];將R0-R2*4地址處的數據計讀出,保存到R1中(R0,R2的值不變)
        從尋址方式的地址計算方法分,加載/存儲指令有以下4 種形式:
        (1)零偏移。Rn 的值作為傳送數據的地址,即地址偏移量為0。指令舉例如下:
        LDR Rd,[Rn]
        (2)前索引偏移。在數據傳送之前,將偏移量加到Rn 中,其結果作為傳送數據的存儲地址。若使用后綴“!”,則結果寫回到Rn中,且Rn 值不允許為R15。指令舉例如下:
        LDR Rd,[Rn,#0x04]!
        LDR Rd,[Rn,#-0x04]
        (3)程序相對偏移。程序相對偏移是索引形式的另一個版本。匯編器由PC 寄存器計算偏移量,並將PC寄存器作為Rn 生成前索引指令。不能使用后綴“!”。指令舉例如下:
        LDR Rd,label ;label 為程序標號,label 必須是在當前指令的±4KB范圍內
        (4) 后索引偏移。Rn 的值用做傳送數據的存儲地址。在數據傳送后,將偏移量與Rn相加,結果寫回到Rn中。Rn 不允許是R15。指令舉例如下:
        LDR Rd,[Rn],#0x04
        地址對准--大多數情況下,必須保證用於32 位傳送的地址是32 位對准的。
        加載/存儲字和無符號字節指令舉例如下:
        LDR R2,[R5] ;加載R5 指定地址上的數據(字),放入R2 中
        STR R1,[R0,#0x04] ;將R1 的數據存儲到R0 0x04存儲單元,R0 值不變
        LDRB R3,[R2],#1 ;讀取R2 地址上的一字節數據,並保存到R3中,R2=R3 1
        STRB R6,[R7] ;讀R6 的數據保存到R7 指定的地址中,只存儲一字節數據
        加載/存儲半字和帶符號字節。這類LDR/STR 指令可能加載帶符字節\加載帶符號半字、加載/存儲無符號半字。偏移量格式、尋址方式與加載/存儲字和無符號字節指令相同。指令格式如下:
        LDR{cond}SB Rd,<地址> ;加載指定地址上的數據(帶符號字節),放入Rd中
        LDR{cond}SH Rd,<地址> ;加載指定地址上的數據(帶符號字節),放入Rd中
        LDR{cond}H Rd,<地址> ;加載半字數據,放入Rd中,即Rd最低16位有效,高16位清零
        STR{cond}H Rd,<地址> ;存儲半字數據,要存儲的數據在Rd,最低16位有效
        說明:帶符號位半字/字節加載是指帶符號位加載擴展到32 位;無符號位半字加載是指零擴展到32位。
        地址對准--對半字傳送的地址必須為偶數。非半字對准的半字加載將使Rd 內容不可靠,非半字對准的半字存儲將使指定地址的2字節存儲內容不可靠。

        加載/存儲半字和帶符號字節指令舉例如下:

        LDRSB R1[R0,R3] ;將R0 R3地址上的字節數據讀出到R1,高24 位用符號位擴展
        LDRSH R1,[R9] ;將R9 地址上的半字數據讀出到R1,高16位用符號位擴展
        LDRH R6,[R2],#2 ;將R2 地址上的半字數據讀出到R6,高16位用零擴展,R2=R2 1
        SHRH R1,[R0,#2]!;將R1 的數據保存到R2 2 地址中,只存儲低2字節數據,R0=R0 2
        LDR/STR 指令用於對內存變量的訪問,內存緩沖區數據的訪問、查表、外設的控制操作等等,若使
用LDR 指令加載數據到PC 寄存器,則實現程序跳轉功能,這樣也就實現了程序散轉。
        變量的訪問
        NumCount EQU 0x40003000 ;定義變量NumCount
        …
        LDR R0,=NumCount ;使用LDR 偽指令裝載NumCount的地址到R0
        LDR R1,[R0] ;取出變量值
        ADD R1,R1,#1 ;NumCount=NumCount 1
        STR R1,[R0] ;保存變量值
        …
        GPIO 設置
        GPIO-BASE EQU 0Xe0028000 ;定義GPIO 寄存器的基地址
        …
        LDR R0,=GPIO-BASE
        LDR R1,=0x00FFFF00 ;裝載32 位立即數,即設置值
        STR R1,[R0,#0x0C] ;IODIR=0x00FFFF00, IODIR 的地址為0xE002800C
        MOV R1,#0x00F00000
        STR R1,[R0,#0x04] ;IOSET=0x00F00000,IOSET 的地址為0xE0028004
        …
        程序散轉
        …
        MOV R2,R2,LSL #2 ;功能號乘上4,以便查表
        LDR PC,[PC,R2] ;查表取得對應功能子程序地址,並跳轉
        NOP
        FUN-TAB DCD FUN-SUB0
        DCD FUN-SUB1
        DCD FUN-SUB2
        …

       
 LDM和STM
        批量加載/存儲指令可以實現在一組寄存器和一塊連續的內存單元之間傳輸數據。LDM為加載多個寄存器,STM 為存儲多個寄存器。允許一條指令傳送16 個寄存器的任何子集或所有寄存器。指令格式如下:
        LDM{cond}<模式> Rn{!},reglist{^}
        STM{cond}<模式> Rn{!},reglist{^}
        LDM /STM 的主要用途是現場保護、數據復制、參數傳送等。其模式有8種,如下所列:(前面4 種用於數據塊的傳輸,后面4 種是堆棧操作)。
        (1) IA:每次傳送后地址加4
        (2) IB:每次傳送前地址加4
        (3) DA:每次傳送后地址減4
        (4) DB:每次傳送前地址減4
        (5) FD:滿遞減堆棧
        (6) ED:空遞增堆棧
        (7) FA:滿遞增堆棧
        (8) EA:空遞增堆棧
        其中,寄存器Rn 為基址寄存器,裝有傳送數據的初始地址,Rn 不允許為R15;后綴“!”表示最后的地址寫回到Rn中;寄存器列表reglist 可包含多於一個寄存器或寄存器范圍,使用“,”分開,如{R1,R2,R6-R9},寄存器排列由小到大排列;“^”后綴不允許在用戶模式呈系統模式下使用,若在LDM 指令用寄存器列表中包含有PC 時使用,那么除了正常的多寄存器傳送外,將SPSR 拷貝到CPSR 中,這可用於異常處理返回;使用“^”后綴進行數據傳送且寄存器列表不包含PC時,加載/存儲的是用戶模式的寄存器,而不是當前模式的寄存器。
        地址對准――這些指令忽略地址的位[1:0]。
        批量加載/存儲指令舉例如下:
        LDMIA R0!,{R3-R9} ;加載R0 指向的地址上的多字數據,保存到R3~R9中,R0 值更新
        STMIA R1!,{R3-R9} ;將R3~R9 的數據存儲到R1 指向的地址上,R1值更新
        STMFD SP!,{R0-R7,LR} ;現場保存,將R0~R7、LR入棧
        LDMFD SP!,{R0-R7,PC}^;恢復現場,異常處理返回
        在進行數據復制時,先設置好源數據指針,然后使用塊拷貝尋址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB 進行讀取和存儲。而進行堆棧操作時,則要先設置堆棧指針,一般使用SP 然后使用堆棧尋址指令STMFD/LDMFD、STMED。LDMED、STMFA/LDMFA、


示例如下:


【匯編指令】arm指令集之但寄存器數據loadstore (加載存儲) -开发者知识库,第2张

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复