load :加载
store:存储
什么是加载?什么是存储?
如下图:
加载是数据从存储器到CPU内的寄存器;
存储是从CPU寄存器到存储器;
三种基本数据加载与存储指令
一. 单寄存器加载与存储指令
常用的但寄存器加载与存储指令有四条:
LDR/STR:字数据加载/存储指令
LDRB/STRB:字节数据加载/存储指令
LDRH/STRH:半字数据加载/存储指令
LDRSB/LDRSH:有符号数字节/半字加载指令
(1)LDR/STR(字)
格式:LDR/STR{条件}{T} 寄存器Rd,addr
功能:LDR用于从储存器加载数据到寄存器Rd中;若Rd为R15(PC),则实现了程序的跳转;
STR用于将寄存器Rd内数据存储到addr地址的内存中;
{T}:T为可选后缀,若指令中有T,那么即使处理器是在特权模式下, 存储系统也将访问看成处理器是在用户模式下。但是当工作模式正处于用户模式下时,T不能与前索引一起使用;
addr:存储器地址;
地址索引分为:前索引,自动索引和后索引;
前索引:也称为前 变址;特点是本句执行完毕后,基址寄存器的值不变;
举个例子:LDR R5,[R6,#0x04] ;R5=R6+0x04
STR R0,[R4,-R8] ;[R4-R8] = R0
例子中:R6和R4的值不会改变;
自动索引:自动变址;特点:是基址寄存器的值被被改变,值为数据传送地址;
举个例子:LDR R5,[R6,#0x04]! ;R6=R6+0x04;R5 = R6;
STR R0,[R1,R2,LSL #2]! ;R1=(R2<<2),R0=R1;
例子中:R1和R6的值被改变
后索引:后变址;特点:先进行地址数据数据传输,基址寄存器的值后被改变;
举个例子:LDR R5,[R6],#0x04 ;R5=R6;R6=R6+0x04;
STR R6,[R7],#-0x08 ;[R7]=R6,[R7]=[R7]-0x08;
例子中:R6和R7的值被改变了;
(2)LDRB/STRB(字节)
格式:LDRB/STRB{条件}{T} 寄存器Rd,addr
功能:功能与(1)类似,只不过是(1)是字数据,(2)是字节;
LDRB:从储存器地址addr加载数据到寄存器Rd,高24位清0; 这里要注意存储方式:寄存器到存储器虽然是只存储一个字节,但是处理器在进行这一操作时仍然使用的是32位地址总线和32位数据总线;
STRB:从寄存器Rb存储数据到存储器addr;过程是将Rb中的低8位字节储存到addr中的低8位字节;(这里就出现了一个问题:那么如果Rb中)中的[23:16]位的数据也想传过来怎么办?答案是移位,将[23:16]位移位带Rb的低8位再进行储存操作即可);
二. 多寄存器(批量)加载与存储指令
LDM:批量数据加载
STM:批量数据存储
(1)LDM/STM多寄存器(批量)加载/存储指令
格式:LDM/STM{条件}{模式} 基址寄存器Rn{!} , 寄存器列表{^}
功能:
LDM:用于从基址寄存器Rn内读取数据到寄存器列表;多用于出栈操作
栗子:
LDMIA R0!,{R6-R8} ;R6=R0,R7=R0+4;R8=R0+8;R0=R0+8
LDMIB R0!,{R6-R8} ;R6=R0+4,R7=R0+8,R8=R0+12,R0=R0+12;
(关于IA和IB,下面解释)
STM:将寄存器列表所指示的多个寄存器中的值存入到由基址寄存器Rn所指是的储存器中;多用于入栈操作
{!}:可选后缀,若加!后缀,则表示指令执行后将寄存器列表最后一位寄存器的值传送到基址寄存器;否则则基址寄存器的值不变;
{}:可选后缀,若加后缀,则在满足指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据加载与存储之外,还将SPSR复制到CPSR。这个后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器;
{模式}:见下表
(2)堆栈操作
- 栈底固定,先设置栈顶堆栈指针SP(R13)的值;
-LDM完成出栈操作,STM完成进栈操作
-确定堆栈在存储器空间中是向上生长还是向下生长的;向上=递增(Asending),向下=递减(Desending);
-关于满堆栈(Full stack)和空堆栈(Empty stack),下面对建一个网址,写的还是比较清晰的:
http://blog.csdn.net/yueyucanyang/article/details/4510263
堆栈操作的3中基本操作:建栈,进栈,出栈;
建栈:规定栈底在RAM存储器中的位置;
栗子:
LDR R13 , =0x90010
LDR R13 , =0x90010 ;与上一条指令功能一样,此时空栈状态;
ARM制定了ATPCS(程序调用标准) 定义了例程如何被调用,寄存器如何被分配。在ATPCS中,堆栈指针被定义为满递减式堆栈,因此LDMFD和STMFD指令分别用来支持POP操作(出栈)和PUSH(进栈)操作;
STMFD-------PUSH--------进栈 (先改变SP的值再储存)
栗子:
STMFD SP! , {R2-R4} ;SP-4 = R4,SP-8 = R3,SP-12 = R2;SP=SP-12;
LDMFD-------POP--------出栈(先加载再改变SP的值)
栗子:
LDMFD SP!,{R6-R8} ;R8 = SP,R7 = SP-4;R6 = SP-8;SP=SP-12;
三. 单寄存器交换指令
功能:寄存器和储存器数据交换,但是很少用,主要用途在多处理器系统中实现信号量操作,以保证不会同时访问动用的数据结构;
特点:交换指令是数据加载和存储指令的特例,交换指令是原子操作,操作期间阻止其他指令对该存储单元读/写;
常用指令:
SWP :字数据交换指令
SWPB:字节数据交换指令
(1)SWP(字)
格式:SWP{条件} 目的寄存器Rd,源寄存器,[寄存器Rn]
栗子:
SWP R0,R1,[R2] ;[R2]→R0 , R1→[R2];
SWP R0 , R0,[R1] ; [R1]与R0互换数据;
(2)SWPB(字节)
格式:SWPB {条件} 目的寄存器Rd,源寄存器Rm,[寄存器Rn]
栗子:
SWPB R0,R1,[R2] ;[R2]→R0,R0&=0x0000 000F, R1→[R2]
SWPB R0 , R0 , [R1] ;R0和[R1]的低八位互换;
**注意:**指令格式里的寄存器不能是PC,而且三个寄存器都是必不可少的;Rn不能与Rm或目的寄存器Rd相同,但是Rm和Rd可以相同;