ARM汇编指令集的存储器访问指令: LDR & STR & LDM & STM & SWP
这里先总的介绍一下存储器访问指令,然后再详解说前两个(LDR&STR)
ARM存储器访问指令:
ARM处理器是加载/存储体系结构的典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM的加载/存储指令可以实现字、半字、有符号和无符号数字节的操作。批量加载/存储指令可实现一条指令加载/存储多个寄存器的内容,大大提高了效率。SWP指令是一条寄存器和存储器内容交换的指令,可用于信号量操作等。ARM处理器是冯诺依曼存储结构,程序空间、RAM及IO映射空间统一编址,除了对RAM操作以外,对外围IO、程序数据的访问均要通过加载/存储指令进行。
* 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种格式:
①立即数
立即数可以是一个无符号数值,这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
eg:
LDR R1,[R0,#0x12] ; 将R0+0x12地址的数据读出,保存到R1中(R0的值不变)
LDR R1,[R0,#-0x12] ; 将R0-0x12地址处的数据读出,保存到R1中(R0的值不变)
LDR R1,[R0] ; 将R0地址处的数据读出,保存到R1中(零偏移)
②寄存器
寄存器中的数值可以加载到基址寄存器,也可以从基址寄存器中减去这个数值。
eg:
LDR R1,[R0,R2] ; 将R0+R2地址的数据读出,保存在R1中(R0的值不变)
LDR R1,[R0,-R2] ; 将R0-R2地址的数据读出,保存在R1中(R0的值不变)
③寄存器及移位常数
寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。
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中形式:
①零偏移
Rn的值作为传送数据的地址,即地址偏移量为0。
eg:
LDR Rd,[Rn]
②前索引偏移
在数据传送之前,将偏移量加到Rn中,其结果作为传送数据的存储地址,若使用后缀“!”,则结果写回到Rn中,且Rn值不允许是R15。
eg:
LDR Rd,[Rn,#0x04]!
LDR Rd,[Rn,#-0x04]
③程序相对偏移
程序相对偏移是索引形式的另一个版本,汇编器由PC寄存器计算偏移量,并将PC寄存器作为Rn生成前索引指令,不能使用后缀“!”。
eg:
LDR Rd,label ; label为程序标号,label必须是在当前指令的±4KB范围内
④后索引偏移
Rn的值用作传送数据的存储地址,在数据传送后,将偏移量与Rn相加,结果写回到Rn中,Rn不允许是R15。
eg:
LDR Rd,[Rn],#0x04
* 注:关于地址对准问题:大多数情况下,必须保证用于32位传送的地址是32位对准的。
* 注:关于半字/有符号数等操作都与上述类似,使用时参考上面的即可。
* 注:LDR/STR 指令用于对内存变变量的访问,内存缓冲区数据的访问、查表、外围部件的控制操作等等,若使用LDR指令加载数据到PC寄存器,则实现程序跳转功能。