DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1452|回复: 0
打印 上一主题 下一主题

[待整理] 数据传送指令之:多寄存器Load/Store内存访问指令

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-10 07:31:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
        5.4  多寄存器Load/Store内存访问指令

        多寄存器Load/Store内存访问指令也叫批量加载/存储指令,它可以实现在一组寄存器和一块连续的内存单元之间传送数据。LDM用于加载多个寄存器,STM用于存储多个寄存器。多寄存器Load/Store内存访问指令允许一条指令传送16个寄存器的任何子集或所有寄存器。
         
        多寄存器Load/Store内存访问指令主要用于现场保护、数据复制和参数传递等。
         
                                                                       
                       
                                                                        注意
                       
                                                                        多寄存器Load/Store内存访问指令会增加中断延时,因为ARM通常不会打断正在执行的指令去响应中断,而必须等到指令执行完。也就是说,如果一个中断在多寄存器Load/Store内存访问指令执行期间产生,那么处理器在多寄存器Load/Store内存访问指令执行完后才对中断响应。
                       
         
        表5.2总结了多寄存器Load/Store内存访问指令
        表5.2     多寄存器Load/Store内存访问指令
                                                                        指    令
                       
                                                                        作    用
                       
                                                                        操    作
                       
                                                                        LDM
                       
                                                                        装载多个寄存器
                       
                                                                        {Rd}*N←mem32[start address+4*N]
                       
                                                                        STM
                       
                                                                        保存多个寄存器
                       
                                                                        {Rd}*N→mem32[start address+4*N]
                       
         
        5.4.1  多寄存器内存字数据传送指令

        1.LDM(1)指令

        (1)指令编码格式
        LDM(1)指令将数据从连续的内存单元中读取到指令中指定的寄存器列表中的各寄存器中。
         
        当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的字数据将被作为目标地址值,指令执行后程序将从目标地址处开始执行,从而实现了指令的跳转。
         
        指令的编码格式如图5.15所示。
       

        图5.15  LDM(1)指令编码格式

         
        (2)指令的语法格式
         
        LDM{<cond>}<addressing_mode>  <Rn>{!},  <registers>
         
        ① <cond>
        为指令编码中的条件域。它指示LDM(1)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
         
        ② <address_mode>
        指令的寻址方式。确定编码格式中的P、U和W位。
         
        ③ <Rn>
        确定寻址模式所使用的基址寄存器。
        如果r15作为指令的基址寄存器,指令的执行结果不可预知。
         
        ④ !
        设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。
         
                                                                       
                       
                                                                        注意
                       
                                                                        如果基址寄存器包含在指令列表中,当指令执行完后,基址寄存器的值是新加载进的特定内存地址的值。也就是说,即使指令没有出现在指令列表中,基址寄存器的值也可能被修改。
                       
         
        ⑤ <registers>
        被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。
         
                                                                       
                       
                                                                        注意
                       
                                                                        无论寄存器在寄存器列表“{}”中如何排列,都将遵循上述规则。
                       
         
        寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。
         
        (3)指令操作的伪代码
        指令操作伪代码如下面程序段所示。
         
        If  ConditionPass{cond}  then
             Address=start_address
         
             For  i=0  to 14
                 If  register_list==1  then
                     Ri=Memory[address,4]
                     Address=address+4
         
             If  register_list[15]==1  then
                       Value = Memory[address,4]
                       If(architecture version 5 or above)  then
                             Pc= value  AND  0xfffffffe
                             T bit=value[0]
                       Else
                             Pc= value  AND  0xfffffffc
                       Address=address+4
             Assert end_address=address+4
        2.STM(1)指令

        (1)指令编码格式
        STM(1)指令将指令中寄存器列表中的各寄存器数值写入到连续的内存单元中。主要用于块数据的写入、数据栈操作以及进入子程序时保存相关寄存器的操作。
         
        指令编码格式如图5.16所示。
       

        图5.16  STM(1)指令编码格式

         
        (2)指令的语法格式
         
        STM{<cond>}<addressing_mode>  <Rn>{!},  <registers>
        ① <cond>
        为指令编码中的条件域。它指示STM(1)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
         
        ② <address_mode>
        指令的寻址方式。确定编码格式中的P、U和W位。
         
        ③ <Rn>
        确定寻址模式所使用的基址寄存器。
        如果r15作为指令的基址寄存器,指令的执行结果不可预知。
         
        ④ !
        设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。
         
        ⑤ <registers>
        被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。
        寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。
         
        (3)指令操作的伪代码
        指令操作伪代码如下面程序段所示。
         
        If  ConditionPassed{cond}  then
             Address=Start_address
             For  i=0  to  15
                   If  register_list==1
                   Memory[address,4]=Ri
                   Address=address+4
             Assert  end_address==address-4
         
        5.4.2  用户模式多寄存器内存字数据传送指令

        1.LDM(2)指令

        (1)指令编码格式
        LDM(2)指令将数据从连续的内存单元中读取到指令中指定的寄存器列表中的各寄存器中。
         
                                                                       
                       
                                                                        注意
                       
                                                                        与LDM(1)指令不同,PC不能包含在寄存器列表中。
                       
         
        指令的编码格式如图5.17所示。
       

        图5.17  LDM(2)指令编码格式

         
        (2)指令的语法格式
         
        LDM{<cond>}<addressing_mode>  <Rn>,  <registers_without_pc>&circ;&circ;
         
        ① <cond>
        为指令编码中的条件域。它指示LDM(2)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
         
        ② <address_mode>
        指令的寻址方式。确定编码格式中的P位和U位。此指令中W位指定为0。
         
        ③ <Rn>
        确定寻址模式所使用的基址寄存器。
        如果r15作为指令的基址寄存器,指令的执行结果不可预知。
         
        ④ <registers_without_pc>&circ;
        被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。此寄存器列表中不能包含PC寄存器。
         
        如果PC包含在寄存器列表中,指令的执行结果不可预知。
        其他细节可参考LDM(1)指令。
         
        (3)指令操作的伪代码
        指令操作伪代码如下面程序段所示。
         
        If  ConditionPassed{cond}  then
             Address=start_address
             For  i=0  to  14
                  If  register_list==1
                        Ri_usr=Memory[address,4]
                        Address=address+4
             Assert  end_address == address-4
         
        2.STM(2)指令

        (1)指令编码格式
        STM(2)指令将指令中寄存器列表中的各寄存器数值写入到连续的内存单元中。主要用于块数据的写入、数据栈操作以及进入子程序时保存相关寄存器等操作。
         
        指令编码格式如图5.18所示。
       

        图5.18  STM(2)指令编码格式

         
        (2)指令的语法格式
         
        STM{<cond>}<addressing_mode>  <Rn>,  <registers >&circ;
        ① <cond>
        为指令编码中的条件域。它指示LDM(2)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
         
        ② <address_mode>
        指令的寻址方式。确定编码格式中的P位和U位。此指令中W位指定为0。
         
        ③ <Rn>
        确定寻址模式所使用的基址寄存器。
         
        如果r15作为指令的基址寄存器,指令的执行结果不可预知。
        ④ <registers >&circ;
        寄存器列表。只能使用用户模式下的寄存器。
         
        (3)指令操作的伪代码
        指令操作伪代码如下面程序段所示。
         
        If  ConditionPassed{cond}  then
             Address=start_address
             For  i=0  to  15
                   If  register_list == 1
                         Memory[address,4]=Ri_usr
                         Address = address +4
              Assert  end_address == address-4
         
        5.4.3  带状态寄存器的多寄存器内存字数据装载指令(LDM(3))

        (1)指令编码格式
        LDM(3)指令将数据从连续的内存单元中读取数据到寄存器列表中的各寄存器中。它同时将当前处理器模式对应的SPSR寄存器的内容复制到CPSR寄存器中。
         
        当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的数据将被作为目标地址值,指令执行后程序将从目标地址处开始执行,从而实现了指令的跳转。
         
        在ARM v5及以上的版本和T系列的ARM v4版本中,SPSR寄存器的T位将复制到CPSR寄存器的T位,该位决定目标地址处的程序状态。在以前的版本中程序继续执行在ARM状态。
         
        指令的编码格式如图5.19所示。
       

        图5.19  LDM(3)指令编码格式

         
        (2)指令的语法格式
         
        LDM{<cond>}<addressing_mode>  <Rn>{!},  <registers_and_pc>&circ;
         
        ① <cond>
        为指令编码中的条件域。它指示LDM(1)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
         
        ② <address_mode>
        指令的寻址方式。确定编码格式中的P、U和W位。
         
        ③ <Rn>
        确定寻址模式所使用的基址寄存器。
        如果r15作为指令的基址寄存器,指令的执行结果不可预知。
         
        ④ !
        设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。
         
                                                                       
                       
                                                                        注意
                       
                                                                        如果基址寄存器包含在指令列表中,当指令执行完后,基址寄存器的值是新加载进的特定内存地址的值。也就是说,即使指令没有出现在指令列表中,基址寄存器的值也可能被修改。
                       
         
        ⑤ <registers_and_pc>&circ;
        寄存器列表。
         
                                                                       
                       
                                                                        注意
                       
                                                                        在本格式的指令中寄存器列表中必须包含PC寄存器。
                       
         
        被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中的低地址单元,编号高的寄存器对应于内存中的高地址单元。
         
        寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。
         
        该指令执行时将当前处理器模式下的SPSR值复制到CPSR中。指令的其他参数可参见LDM(1)指令格式。
         
        (3)指令操作的伪代码
        指令操作伪代码如下面程序段所示。
         
        If  ConditionPass{<cond>}  then
             Address=start_address
             For i=0  to  14
                   If  register_list==1 then
                         Ri=Memory[address,4]
                         Address=address+4
             CPSR=SPSR
             Value=memory[address,4]
             If {architecture version 4T, 5 or above} and {T bit ==1} then
             Else
                   Pc=value AND oxfffffffc
             Address=address + 4
             Assert end_address=address-4
         
        5.4.4  数据传送指令应用

        LDM/STM批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器,STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。指令格式如下:
         
        LDM{cond}<模式>  Rn{!},regist{&circ;}
        STM{cond}<模式>  Rn{!},regist{&circ;}
         
        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},寄存器排列由小到大排列;“&circ;”后缀不允许在用户模式下,只能在系统模式下使用。若在LDM指令用寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,将SPSR拷贝到CPSR中,这可用于异常处理返回;使用“&circ;”后缀进行数据传送且寄存器列表不包含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}&circ;     ;恢复现场,异常处理返回
         
        在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储。而进行堆栈操作时,则要先设置堆栈指针,一般使用SP然后使用堆栈寻址指令STMFD/LDMFD、STMED/LDMED、STMEA/LDMEA实现堆栈操作。
         
        多寄存器传送指令如例5.3所示。其中r1为指令执行前的基址寄存器,r1’则为指令执行后的基址寄存器。
         
        【例5.3】多寄存器传送指令示意。
         
        (1)STMIA  r1,{r5~r7}

       

        (2)STMIB  r1!,{r5~r7}

       

        (3)STMDA  r1!,{r5~r7}

       

        (4)STMDB  r1!,{r5~r7}

       

         
        数据是存储在基址寄存器的地址之上还是之下,地址是存储第一个值之前还是之后、增加还是减少,如表5.3所示。
        表5.3 多寄存器Load/Store内存访问指令映射
                                                                         
                       
                                                                        向 上 生 长
                       
                                                                        向 下 生 长
                       
                                                                        满
                       
                                                                        空
                       
                                                                        满
                       
                                                                        空
                       
                                                                        增加
                       
                                                                        之前
                       
                                                                        STMIB
                       
                                                                         
                       
                                                                         
                       
                                                                        LDMIB
                       
                                                                        STMFA
                       
                                                                         
                       
                                                                         
                       
                                                                        LDMED
                       
                                                                        之后
                       
                                                                         
                       
                                                                        STMIA
                       
                                                                        LDMIA
                       
                                                                         
                       
                                                                         
                       
                                                                        STMEA
                       
                                                                        LDMFD
                       
                                                                         
                       
                                                                        增加
                       
                                                                        之前
                       
                                                                         
                       
                                                                        LDMDB
                       
                                                                        STMDB
                       
                                                                         
                       
                                                                         
                       
                                                                        LDMEA
                       
                                                                        STMFD
                       
                                                                         
                       
                                                                        之后
                       
                                                                        LDMDA
                       
                                                                         
                       
                                                                         
                       
                                                                        STMDA
                       
                                                                        LDMFA
                       
                                                                         
                       
                                                                         
                       
                                                                        STMED
                       
         
        【例5.4】使用LDM/STM进行数据复制。
         
        LDR  r0,=SrcData           ;设置源数据地址
        LDR  r1,=DstData           ;设置目标地址
        LDMIA   r0,{r2~r9}        ;加载8字数据到寄存器r2~r9
        STMIA   r1,{r2~r9}        ;存储寄存器r2~r9到目标地址
         
        【例5.5】使用LDM/STM进行现场寄存器保护,常在子程序或异常处理使用。
         
        SENDBYTE
              STMFD     SP!,{r0~r7,LR}        ;寄存器压栈保护
           …….
              BL        DELAY                  ;调用DELAY子程序
           …….
              LDMFD     SP!,{r0~r7,PC}        ;恢复寄存器,并返回
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2024-11-27 12:47 , 耗时 0.098094 秒, 22 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表