嵌⼊式LinuxARM汇编(三)——ARM汇编指令
⼀、ARM汇编语⾔基本结构
AREA Init, CODE, READONLY
ENTRY
Start
LDR R0, =0x3FF5000
LDR R1, 0xFF
STR R1, [R0]
LDR R0, =0x3FF5008
LDR R1, 0x01
STR R1, [R0]
... ... ... ... ... ...
END
⼆、ARM处理器寻址⽅式
寻址⽅式是根据指令中给出的地址码字段来实现寻真实操作数地址的⽅式。ARM处理器有九种寻址⽅式,寄存器寻址、⽴即数寻址、寄存器偏移寻址为数据处理指令操作数寻址⽅式,寄存器间接寻址、基址寻址、多寄存器寻址、堆栈寻址、相对寻址为存储器访问指令操作数寻址⽅式。
1、寄存器寻址
操作数的值存在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执⾏时直接取出寄存器值操作。例如:MOV R0,R1
SUB R0,R1,R2
2、⽴即寻址
⽴即寻址指令中的操作码字段部分后⾯的地址码部分就是操作数本⾝,即数据包含在指令当中。例如:
MOV R0,#0xff
⽴即数要以“#”为前缀,⼗六进制以“0x”表⽰
3、寄存器偏移寻址
寄存器偏移寻址是ARM指令集特有的寻址⽅式,当第2操作数是寄存器,在执⾏操作之前,可以做⼀次移位操作。
MOV R0,R2,LSL #3
ANDS R1,R1,R2,LSL R3
4、寄存器间接寻址
寄存器间接寻址指令中的地址码给出的是⼀个通⽤寄存器的编号,所需的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。
LDR R1,[R2] ;将R2指向的单元中的数据保存再R1中
SWP R1,R1,[R2] ;将寄存器R1的值和R2指向的单元中进⾏内容交换
5、基址寻址
基址寻址就是将基址寄存器的内容与指令中给出的偏移量进⾏相加,形成操作数的有效地址。基址寻址⽤于访问基址附近的存储单元,常⽤于查表、数组操作以及功能不见寄存器访问等。
LDR R2,[R3,#0x0c] ;读取R3 0x0c地址指向的存储单元的内容,放⼊R2
STR R1,[R0,#-4]! ;先R0=R0-4,然后把R1的值寄存到R0所指向的单元中
LDR R1,[R0,R3,LSL #1] ;将R0 R3*2地址上的单元的内容读出,并存⼊R1中
6、多寄存器寻址
多寄存器寻址即⼀次可传送⼏个寄存器的值,允许⼀条指令传送16个寄存器的任何⼦集或所有的存储器。
LDMIA R1!,{R2-R7,R12};将R1指向的单元中的数据读出到R2---R7、R12中(R1⾃⾃动)
STMIA R0!,{R2-R7,R12};将R2---R7、R12中的数据⼀次读⼊到R0指向的单元中(R0⾃动)
7、堆栈寻址
堆栈是⼀种按特定顺序进⾏存取的存储区,操作顺序分为“先进后出”和“后进先出”,堆栈寻址是隐含的,它使⽤⼀个专门的寄存器(堆栈指针)指向的存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。
STMFD SP!,{R1-R7,LR} ;将R1---R7、LR⼊栈。满递减堆栈
LDMFD SP!,{R1-R7,LR} ;数据出栈,放⼊R1---R7、LR寄存器,满递减堆栈
8、块拷贝寻址
arm嵌入式系统期末考试多寄存器传送指令⽤于将⼀块数据从存储器的某⼀位置拷贝到另⼀位置。
STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。
;存储指针在保存第⼀个值之后增加,
;增长⽅向为向上增长。
STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。
;存储指针在保存第⼀个值之前增加,
;增长⽅向为向上增长。
9、相对寻址
相对寻址是基址寻址的⼀种变通。由程序计数器PC提供基址地址,指令中的地址码字段为偏移量。两者相加后得到的地址即为操作数的有效地址。
三、指令格式
ARM指令的基本格式:
<opcode>[<con>][S] <Rd>, <Rn>{,operand2}
opcode:指令助记码,如:MOV
con:执⾏条件,如NE,EQ
S:是否影响CPSR寄存器的值,设置时影响CPSR
Rd:⽬标寄存器
Rn:第⼀个操作数的寄存器
operand2:第⼆个操作数
条件码表
四、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中,指令格式:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论