嵌入式Linux ARM汇编(三)——ARM汇编指令(二)
四、ARM存储器访问指令
ARM处理器是加载/存储体系结构的典型RISC处理器,对存储器的访问只能用加载和存储指令实现。ARM的加载/存储指令可以实现字、半字、字节操作。
1、LDR和STR
加载/存储字和无符号字节指令。使用单一数据传送指令来装载和存储单一字节或字的数据。LDR指令用于从内存中读取数据放入内存中,STR指令用于将寄存器中的数据保存到内存中。
指令格式如下:
LDR[cond][T] Rd,<地址>;
加载指定地址上的数据(字),放入Rd中
STR[cond][T] Rd,<地址>;
存储数据(字)到指定地址的存储单元,要存储的数据在Rd中
LDR[cond]B[T] Rd,<地址>;加载字节数据,放入Rd中,Rd低字节有效
STR[cond]B[T] Rd,<地址>;存储字节数据,要存储的数据在Rd中
指令T表示在处理器特权模式下,存储系统也将访问看做是在用户模式下。
STR R0,[R1],#8;将R0中内容写入R1为地址的内存中,并将新地址R1+8写入R1。
STR R0,[R1,#8];将R0中的字数据写入以R1+8为地址的存储器中。
LDR/STR指令寻址非常灵活,由两部分组成,一部分为基址寄存器,可以是任一通用寄存器,另一部分为地址偏移量,由以下三种格式:
a、立即数
立即数可以是一个无符号数值,这个数值可以加到基址寄存器或由基址寄存器减去,例如:
LDR R0,[R1,#0x12];将R1+0x12地址处的数据读出保存到R0寄存器中
LDR R0,[R1,#-0x12];将R1-0x12地址处的数据读出保存到R0寄存器中
LDR R0,[R1];将R1地址处的数据读出保存到R0寄存器中
b、寄存器
寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个值,例如:
LDR R0,[R1,R2];将R1+R2地址处的数据读出,保存到R0寄存器中
LDR R0,[R1,-R2];将R1-R2地址处的数据读出,保存到R0寄存器中
c、寄存器及移位常数
基址寄存器加上或减去寄存器移位后的值
LDR R0,[R1,R2,LSL#2];将R1+R2*4地址处的数据读出,保存到寄存器R0
LDR R0,[R1,-R2,LSL#2];将R1-R2*4地址处的数据读出,保存到寄存器R0
LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。 该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目 的地址,从而可以实现程序流程的跳转。
LDRH指令的格式为:
LDR{条件}H 目的寄存器,<存储器地址>
LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。 该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作 目的地址,从而可以实现程序流程的跳转。
STRB指令的格式为:
STR{条件}B 源寄存器,<存储器地址>
STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
STRH指令的格式为:
STR{条件}H 源寄存器,<存储器地址>
STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。
应用示例:
GPIO设置:
GPIO_BASE EQU 0xE0028000;定义GPIO寄存器的基地址
LDR R0,=GPIO_BASE
LDR R1,=0x00FFFFFF00
STR R1,[R0,#0x0C];将0xE002800C地址的值设为0x00FFFFFF00
MOV R1,0x00F00000
STR R1,[R0,#0x04];将0xE0028004地址的值设为0x00F00000
2、LDM和STM
批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据,指令格式如下:
LDM[cond]<模式> Rn[!],reglist{^}
STM[cond]<模式> Rn[!],reglist{^}
模式有八种:
IA 每次传送后地址加4;
IB 每次传送前地址加4;
DA 每次传送后地址减4;
DB 每次传送前地址减4;
FD 满递减堆栈;
ED 空递减堆栈;
FA 满递增堆栈;
EA 空递增堆栈;
{!}为可选后缀,若选用该后缀,则当数据 传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。
{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表 示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
指令示例:
STMFD R13!,{R0,R4-R12,LR} ;将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈。
LDMFD R13!, {R0,R4-R12,PC}^ ;将堆栈内容恢复到寄存器(R0,R4到R12,PC),SPSR复制到CPSR
LDM/STM用途是现场保护、数据复制、参数传送
3、SWP
寄存器和存储器交换指令,指令格式:
SWP[cond][B] Rd,Rm,[Rn]
将Rn的值为地址的内存单元的值读取到Rd寄存器中,同时将寄存器Rm的值写入该内存单元。
如果有B,则交换字节,否则交换32位字;
五、ARM数据处理指令
数据处理指令分为数据传送指令、算数逻辑运算指令、比较指令
数据处理指令只能对寄存器的内容进行操作
1、数据传送指令
A、MOV
MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S 时指令不更新CPSR中条件标志位的值。
指令格式:
MOV[con][S] Rd,operand2
MOV R0,#0x04
MOV R0,R1
MOVS R3,R2,LSL#2
MOV PC,LR;PC=LR,子程序返回
B、MVN
MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MOV指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。指令格式:
MOV[con][S] Rd,operand2
MVN R0,R1
MVN R2,#0xFF;R2位0xFFFFFF00
2、算数逻辑运算指令
A、ADD加法运算指令
指令格式:
ADD[con][S] Rd,Rn,operand2
将operand2数据与Rn的值相加,结果保存到Rd寄存器
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
ADD R0,R1,R2
ADD R0,R1,#0x12
ADDS R0,R1,R2,LSL#2
B、SUB减法运算指令
SUB[con][S] Rd,Rn,operand2
用寄存器Rn的值减去operand2,结果保存在Rd中,指令格式:
SUBS R0,R0,#1
SUBS R0,R1,R2
RBS逆向减法指令
用寄存器operand2减去Rn,结果保存到Rd中,指令格式:
RBS[con][S] Rd,Rn,operand2
RSB R0,R1,#0x100;R0=0x100-R1
C、ADC带进位加法指令
将operand2的数据与Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器,指令格式:
ADC[con][S] Rd,Rn,operand2
D、AND逻辑与操作指令
将寄存器operand2的值与寄存器Rn的值按位作逻辑与操作,结果保存到Rd中,指令格式:
AND[con][S] Rd,Rn,operand2
ANDS R0,R1,#0x01
AND R0,R1,R2
E、ORR逻辑或操作指令
将寄存器operand2的值与寄存器Rn的值按位作逻辑或操作,结果保存到Rd中,指令格式:
ORR[con][S] Rd,Rn,operand2
ORR R0,R0,#0x0F;将R0的低4位置1
F、EOR逻辑异或操作指令
将寄存器operand2的值与寄存器Rn的值按位作逻辑异或操作,结果保存到Rd中,指令格式:
ERR[con][S] Rd,Rn,operand2
H、BIC位清零操作指令
将寄存器Rn的值与寄存器operand2的值反码按位作逻辑与操作,结果保存到Rd中,指令格式:
BIC[con][S] Rd,Rn,operand2
BIC R1,R1,#0x0F
3、比较指令
A、CMP比较指令
用寄存器Rn的值减去寄存器operand2的值,根据操作的结果更新CPSR中相应的条件标志位,以便后面的指令根据相应的条件标志位判断是否执行,指令格式:
CMP[con] Rn,operand2
B、CMN负数比较指令
CMN[con] Rn,operand2
CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较,同时更新CPSR中条件标志位的值。该指令实际完成操作数1和操作数2相 加,并根据结果更改条件标志位。
指令示例:
CMN R1,R0 ;将寄存器R1的值与寄存器R0的值相加,并根据 结果设置CPSR的标志位
4、乘法指令
A、MUL 32位乘法指令
将Rm与Rs中的值相乘,结果的低32位保存到Rd中,指令格式:
MUL[con][S] Rd,Rm,Rs
MUL R0,R1,R2
B、MLA 32位乘法叠加指令
将Rm与Rs中的值相乘,结果再与Rn相加,低32位保存到Rd中,指令格式:
MLA[con][S] Rd,Rm,Rs,Rn
MLA R0,R1,R2,R3
C、UMULL 64位无符号乘法指令
将Rm与Rs的值作无符号数相乘,结果的低32位保存到RdLo中,高32位保存到RdHi中,指令格式:
UMULL[con][S] RdLo,RdHi,Rm,Rs
UMULL R0,R1,R4,R5;(R1,R0)=R4*R5
D、SMULL 64位有符号乘法指令
将Rm与Rs的值作有符号数相乘,结果的低32位保存到RdLo中,高32位保存到RdHi中,指令格式:
SMULL[con][S] RdLo,RdHi,Rm,Rs
SMULL R0,R1,R4,R5;(R1,R0)=R4*R5