1.19.ARM汇编指令集7之存储器访问指令(LDR和STR)

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寄存器,则实现程序跳转功能。