多寄存器寻址指令ldmia/ldmib和ARM存储器访问指令——多寄存器存取

多寄存器和堆栈寻址的用法:多寄存器寻址:LDMIA,LDMIB,STMIA,STMIB,LDMDA,LDMDB,STMDA,STMDB;
堆栈寻址:LDMFA,LDMFD,STMFA,STMFD,LDMEA,LDMED,STMEA,STMED;

弄清堆栈寻址的SP的变化:LDMFA,LDMFD,STMFA,STMFD,LDMEA,LDMED,STMEA,STMED;

IA: 每次传送后地址加4;
IB: 每次传送前地址加4;
DA: 每次传送后地址减4;
DB: 每次传送前地址减4;
FD: 满递减堆栈;
ED: 空递减堆栈;
FA: 满递增堆栈;
EA: 空递增堆栈。




1、多寄存器寻址:
LDMIA R0!,{R1-R4}  

                               ;R1<----[R0]
                               ;R2<----[R0+4]
                               ;R3<----[R0+8]
                               ;R4<----[R0+12]         

例如:

所有的示例指令执行前:
mem32[0x1000C] = 0x04
mem32[0x10008] = 0x03
mem32[0x10004] = 0x02
mem32[0x10000] = 0x01
r0 = 0x00010010
r1 = 0x00000000
r3 = 0x00000000
r4 = 0x00000000
1) ldmia r0!, {r1-r3} 2) ldmib r0!, {r1-r3}
执行后:                      执行后:
r0 = 0x00100000    r0 = 0x00100000
r1 = 0x01                   r1 = 0x02
r2 = 0x02                   r2 = 0x03
r3 = 0x03                   r3 = 0x04


2、堆栈寻址:
STMFD入栈指令,相当于STMDB
STMFD SP!,{R2-R4}                            ;[SP-4]<---R4
                                             ;[SP-8]<---R3 
                                             ;[SP-12]<---R2   
LDMFD出栈指令,相当于LDMIA
LDMFD SP!,{R6-R8}                ;R6<----[SP]
                                 ;R7<----[SP+4]
                                 ;R8<----[SP+8]

•LDR和STR——字和无符号字节加载/存储指令
  LDR指令用于从内存中读取单一字或字节数据存入寄存器中,STR指令用于将寄存器中的单一字或字节数据保存到内存。指令格式如下:
  LDR{cond}{T} Rd,<地址>  ;将指定地址上的字数据读入Rd
  STR{cond}{T} Rd,<地址>  ;将Rd中的字数据存入指定地址
  LDR{cond}B{T} Rd,<地址>  ;将指定地址上的字节数据读入Rd
  STR{cond}B{T} Rd,<地址>  ;将Rd中的字节数据存入指定地址
•LDR和STR——字和无符号字节加载/存储指令
   LDR/STR指令寻址非常灵活,它由两部分组成,其中一部分为一个基址寄存器,可以为任一个通用寄存器;另一部分为一个地址偏移量。地址偏移量有以下3种格式:
    立即数。立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
    如:LDR  R1,[R0,#0x12] ;R1<-[R0+0x12]
    寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
    如:LDR  R1,[R0,R2]  ; R1<-[R0+R2]
       LDR  R1,[R0,-R2]  ; R1<-[R0-R2]
    寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
    如:LDR  R1,[R0,R2,LSL #2]

 多寄存器加载/存储指令格式如下:
LDM{cond}<模式>  Rn{!},reglist{^} ;
STM{cond}<模式>  Rn{!},reglist{^} ;
        多寄存器加载/存储指令格式如下:
LDM{cond}<模式>  Rn{!},reglist{^} ;
STM{cond}<模式>  Rn{!},reglist{^} ;
cond:指令执行的条件;
模式:控制地址的增长方式,一共有8种模式;
!:表示在操作结束后,将最后的地址写回Rn中;
reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列;
^:可选后缀。允许在用户模式或系统模式下使用。它有以下两个功能:
1)若op是LDM且寄存器列表包含R15时,那么除了正常的多寄存器传送外,还将SPSR也复制到CPSR中。这用于异常处理返回,仅在异常模式下使用。
2)数据传入或传出的是用户模式下的寄存器,而不是当前模式的寄存器。

多寄存器加载/存储指令的8种模式如下表所示,右边四种为堆栈操作、左边四种为数据传送操作。
模式
说明
模式
说明
IA
每次传送后地址加4
FD
满递减堆栈
IB
每次传送前地址加4
ED
空递减堆栈
DA
每次传送后地址减4
FA
满递增堆栈
DB
每次传送前地址减4
EA
空递增堆栈
数据块传送操作
堆栈操作
        进行数据复制时,先设置好源数据指针和目标指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储 。
        进行堆栈操作操作时,要先设置堆栈指针(SP),然后使用堆栈寻址指令STMFD/LDMFD 、STMED/LDMED、STMFA/LDMFA和STMEA/LDMEA实现堆栈操作。
数据块传送
存储
堆栈操作
压栈
说明
 
数据块传送
加载
堆栈操作
出栈
说明
STMDA
STMED
空递减
LDMDA
LDMFA
满递减
STMIA
STMEA
空递增
LDMIA
LDMFD
满递增
STMDB
STMFD
满递减
LDMDB
LDMEA
空递减
STMIB
STMFA
满递增
LDMIB
LDMED
空递增
;使用数据块传送指令进行堆栈操作
STMDA R0!,{R5-R6}将R5、R6存入相应的R0指向的地址对应的内存
. . .
LDMIB R0!,{R5-R6}将R0指向的地址对应的内存的内容存入R5和R6
;使用堆栈指令进行堆栈操作
STMED R13!,{R5-R6}
. . .
LDMED R13!,{R5-R6}这一段代码的两个都是ED

两段代码的执行结果是一样的,但是使用堆栈指令的压栈和出栈操作编程很简单(只要前后一致即可),而使用数据块指令进行压栈和出栈操作则需要考虑空与满、加与减对应的问题。(相当于堆栈指令做了封装)

你可能感兴趣的:(linux)