ARM指令集讲解.docx
《ARM指令集讲解.docx》由会员分享,可在线阅读,更多相关《ARM指令集讲解.docx(15页珍藏版)》请在冰豆网上搜索。
ARM指令集讲解
ARM指令和指令系统:
指令是指示计算机某种操作的命令,指令的集合称为指令系统。
指令系统的功能强弱很大程度上决定了这类计算机智能的高低,它集中地反应了微处理器的硬件功能和属性。
ARM指令在机器中的表示格式是用32位的二进制数表示。
如ARM中有一条指令为
ADDEQS R0,R1,#8;
其二进制代码形式为:
31~28|27~25|24~21|20|19~16| 15~12|11~0
0000|001|0100|1|0001|0000|000000001000
cond|opcode|Rn|Rd|Op2
ARM指令格式一般如下:
{}{s},{,}
格式中<>的内容是必不可少的,{}中的内容可忽略
表示操作码。
如ADD表示算术加法
{}表示指令执行的条件域。
如EQ、NE等,缺省为AL。
{S}决定指令的执行结果是否影响CPSR的值,使用该后缀则指令执行结果影响CPSR的值,否则不影响
表示目的寄存器
表示第一个操作数,为寄存器
表示第二个操作数,可以是立即数。
寄存器和寄存器移位操作数
ARM指令后缀:
S、!
S后缀:
指令中使用S后缀时,指令执行后程序状态寄存器的条件标志位将被刷新,不使用S后缀时,指令执行后程序状态寄存器的条件标志将不会发生变化。
S后缀常用于对条件进行测试,如是否有溢出,是否进位等,根据这些变化,就可以进行一些判断,如是否大于,相等,从而影响指令执行的顺序。
!
后缀:
如果指令地址表达式中不含!
后缀,则基址寄存器中的地址值不会发生变化。
加上此后缀后,基址寄存器中的值(指令执行后)= 指令执行前的值+地址偏移量
(1)!
后缀必须紧跟在地址表达式后面,而地址表达式要有明确的地址偏移量
(2)!
后缀不能用于R15(PC)的后面
(3)当用在单个地址寄存器后面时,必须确信这个寄存器有隐性的偏移量,例如“STMDB R1!
,{R3,R5,R7}”。
此时地址基址寄存器R1的隐性偏移量为4(一条指令占32位,即4个字节)
指令的条件码:
31-28位4个字节存储,共16个条件码
条件码助记符后缀标志含义
0000EQZ置位相等
0001NEZ清零不相等
0010CSC置位无符号数大于或等于
0011CCC清零无符号数小于
0100MIN置位负数
0101PLN清零正数或零
0110VSV置位溢出
0111VCV清零未溢出
1000HIC置位Z清零无符号数大于
1001LSC清零Z置位无符号数小于或等于
1010GEN等于V带符号数大于或等于
1011LTN不等于V带符号数小于
1100GTZ清零且(N等于V)带符号数大于
1101LEZ置位或(N不等于V)带符号数小于或等于
1110AL忽略无条件执行
ARM指令分类:
六大类
ARM指令集可以分为数据处理指令,数据加载指令和存储指令,分支指令,程序状态寄存器(PSR)处理指令,协处理器指令和异常产生指令六大类。
ARM指令的寻址方式:
8类
ARM指令的寻址方式一般可以分为8类:
立即数寻址,寄存器寻址,寄存器间接寻址,寄存器移位寻址,基址变址寻址,多寄存器寻址,相对寻址,堆栈寻址等
举例:
MOVR0,#15;立即数15放入寄存器R0中
ADDR0,R1,R2;R0<=R1+R2
LDRR0,[R4];R0<=[R4](R4中存放的是一个指针变量,[]表示取改地址值指向的内容)
ADDR0,R1,R2,LSL#1;R0<=R1+R2(R2左移一位后的值)
MOVR0,R1,LSLR3;R0 <= R1(R1左移R3位后)
LDRR0,[R1,#4];R0 <= [R1+4]
LDRR0,[R1,#4]!
;R0 <= [R1+4],R1 <=R1+4。
同时更新基址
LDRR0,[R1],#4;R0 <= [R1],R1 <=R1+4
LDRR0,[R1,R2];R0 <= [R1+R2]
LDMIAR0!
,{R1-R4};R1 <= [R0]、R1 <= [R0+4]、R1 <= [R0+8]、R1 <= [R0+12]
BLproc;跳转到子程序proc处执行,执行完毕后返回(L标记,带返回的跳转)。
STMFDR13!
,{R0-R4};R0-R4压栈,FD为满栈递减,地址从高到低,R13为SP堆栈指针
LDMFDR13!
,{R0-R4};R0-R4出栈,FD为满栈递减
ARM寄存器数据处理指令:
1、数据处理指令机器编码格式:
31~28| 27~2625|24~21|20|19~16| 15~12|11~0
cond| 00I|opcode|S|Rn|Rd|Op2
cond:
指令执行的条件码
I:
用于区别第二操作数是立即数(I=1)还是寄存器移位(I=0)
opcode:
数据处理指令操作码
S:
用于设置条件码,S=0时,条件码不改变,S=1时,条件码根据具体指令的结果修改
Rn:
第一操作数寄存器
Rd:
目标寄存器
Op2:
第二操作数,该数可以是立即数或寄存器移位数
2、数据传送指令:
MOV MVN
MOVR1,R0;将寄存器R0的值传送到寄存器R1
MOVPC,R14;将寄存器R14的值传送到PC,常用于子程序返回
MOVR1,R0,LSL#3;将寄存器R0的值左移3位后传送到R1
MOVR0,#5;将立即数5传送到寄存器R0
MVNR0,#0;将立即数0按位取反后传送到寄存器R0中,完成后R0=-1
MVNR1,R2;将R2按位取反后,结果存到R1
3、移位指令:
LSL、LSR、ASR、ROR、RRX
MOVR0,R1,LSL#1;寄存器R1左移一位后传送到R0
MOVSR0,R1,LSL#1;寄存器R1左移一位后传送到R0,并更新状态标志位
MOVSR0,R1,LSR#1;寄存器R1右移一位后传送到R0,并更新状态标志位
MOVSR0,R1,ASR#1;寄存器R1算术右移一位后传送到R0,并更新状态标志位
;算术右移,第一位符号位不变
MOVR0,R1,ROR#1;寄存器R1循环右移一位后传送到R0
MOVSR0,R1,RRX;寄存器R1循环右移一位后传送到R0,用C标志位作为最高位扩展
4、算术指令:
ADD、ADC、SUB、SBC、RSB、RSC
ADDR0,R1,R2;寄存器R1和R2的值相加后传送到R0
ADDR0,R1,#5;寄存器R1的值加上5后传送到R0
ADDR0,R1,R2,LSL#2;寄存器R2左移两位后与R1相加,得到的结果传送到R0
ADDR0,R1,R2,LSLR3;寄存器R2左移R3后与R1相加,得到的结果传送到R0
ADDSR0,R2,R4;64位加,低位放在R0
ADCR1,R3,R5;64位加,高位放在R1,注意要加上低位的进位
SUBR0,R1,R2;寄存器R1和R2的值相减后传送到R0
SUBR0,R1,#6;寄存器R1的值减6后传送到R0
SUBR0,R1,R2,LSL#1;R1与寄存器R2左移一位后的值相减,得到的结果传送到R0
SUBSR0,R2,R4;64位减,低位放在R0
SBCR1,R3,R5;64位减,高位放在R1,注意要减去低位的借位
RSBR0,R1,R2;寄存器R2和R1的值相减后传送到R0,注意是R2-R1,方向相反
RSBR0,R1,#6;6与寄存器R1的值相减后传送到R0
RSBR0,R1,R2,LSL#1;寄存器R2左移一位后与R1相减,得到的结果传送到R0
RSCR0,R1,R2;寄存器R2和R1的值相减,再减去借位后传送到R0
5、逻辑运算指令:
AND、ORR、EOR、BIC
ANDR0,R0,#0xF;R0的值与0xF相位与后的值传送到R0
ORRR0,R0,#9;R0的值与9相位与后的值传送到R0
EORR0,R0,#0xF;R0的值与0xF相异或后的值传送到R0
BICR0,R0,#9;位清除指令R0的第0位和第3位清零
6、比较指令:
CMP、CMN、TST、TEQ
CMPR1,#10;将寄存器R1的值与10相减,并设置CPSR标志位
ADDGTR0,R0,#5;如果R1>10,则执行ADDGT指令,将R0加5
CMNR0,R1;R0-(-R1),反值比较,影响CPSR标志位
CMNR0,#10;R0-(-10),反值比较,影响CPSR标志位
TSTR1,#3;检查R1中第0位和第1位是否为1,根据结果更新条件标志位
TEQR1,R2;将寄存器R1的值与寄存器R2的值进行按位异或,
;并根据结果设置CPSR的标志位
7、乘法指令:
MUL、MLA、SMULL、SMLAL、UMULL、UMLAL
MULR0,R1,R2;R1和R2相乘的结果发送到R0
MULSR0,R1,R2;R1和R2相乘的结果发送到R0,同时设置CPSR的相关条件标志位
MLAR0,R1,R2,R3;R1和R2相乘的结果再加上R3后发送到R0
MLASR0,R1,R2,R3;R1和R2相乘的结果再加上R3后发送到R0,更新CPSR标志位
SMULLR0,R1,R2,R3;R2和R3相乘的结果的低32位放在R0,高32位放在R1
SMLALR0,R1,R2,R3;R2和R3相乘的结果的低32位加上R0后放在R0,
;高32位加上R1后放在R1
UMULLR0,R1,R2,R3;无符号数相乘,结果与SMULL类似
UMLALR0,R1,R2,R3;无符号数乘加,结果与SMLAL类似
ARM数据加载和存储指令:
1、数据加载和存储的方向。
寄存器到存储器方向:
Store;从存储器到寄存器方向:
Load
数据加载和存储指令共有三种类型:
单寄存器加载和存储指令,多寄存器加载和存储指令和交换指令
2、数据加载与存储器指令寻址
LDRR5,[R6,#0x08];R6寄存器加0x08的和的地址值内的数据传送到R5
STRR6,[R7],#-0x08;R6寄存器的数据传送到R7存储的地址值指向的存储空间,
;同时更新R7寄存器的内容为R7-0x08
LDRR5,[R6,R3];R6寄存器加R3的和的地址值内的数据传送到R5
STRR6,[R7],-R8;R6寄存器的数据传送到R7存储的地址值指向的存储空间,
;同时更新R7寄存器的内容为R7-R8
LDRR3,[R2,R4,LSL#2];R3<==[ R2+R4(R4左移两位) ]
LDRR3,[R2],-R4,LSR#3;R3<==[R2],R2=R2-R4(R4右移三位)
LDRR4,START;将标号START标定的空间的数据加载到R4中
3、地址索引:
前索引、自动索引、后索引
1】前索引:
前索引也称为前变址,这种索引是在指令执行前把偏移量和基址相加减,得到的值作为变量的地址。
如:
LDRR5,[R6,#0x04]
STRR0,[R5,-R8]
2】自动索引:
自动索引也称为自动变址,有时为了修改基址寄存器的内容,使之指向数据传送地址,可使用这种方法自动修改基址寄存器,如:
LDRR5,[R6,#0x04]!
3】后索引:
后索引也被称为后变址,后索引就是用基址寄存器的地址值寻址,找出操作数进行操作,操作完成后,再把地址偏移量和基址相加/减,结果送到基址寄存器,作为下一次寻址的基址。
如:
LDRR5,[R6],#0x04
STRR6,[R7],#-0x08
4、单寄存器加载和存储指令:
LDR/STR、LDRB/STRB、LDRH/STRH、LDRSB/LDRSH
1】字数据加载/存储指令格式:
31~28| 27~26| 25 24232221 20|19~16| 15~12|11~0
cond| 01| I P U B W L |Rn|Rd|Op2
cond:
指令执行的条件编码
I、P、U、W:
用于区别不同的地址模式(偏移量)。
I为0时,偏移量为12位立即数;I为1时,偏移量为移位寄存器移位
P表示前/后索引
U表示加/减
W表示回写
L:
L为1时表示加载,L为0时表示存储
B:
B为1表示字节访问,B为0表示字访问
Rd:
源/目标寄存器
Rn:
基址寄存器
Op2:
表示偏移量是一个12位的无符号二进制数,与Rn一起构成地址addr
2】存储器<==>寄存器 LDR/STR
LDR指令用于从存储器中间一个32位的字数据加载到目的寄存器Rd中。
该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。
当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当做目的地址,从而实现程序流程的跳转。
LDRR4,START;将存储地址为START的字数据读入R4
STRR5,DATA1;将R5存入存储地址为DATA1中
LDRR0,[R1];将存储器地址为R1的字数据读入寄存器R0
LDRR0,[R1,R2];将存储器地址为R1+R2的字数据读入寄存器R0
LDRR0,[R1,#8];将寄存器R1+8的内容读入寄存器R0
LDRR0,[R1,R2,LSL#2];将R1+R2*4的字数据读入寄存器R0
STRR0,[R1,R2]!
;将R0字数据存入存储器地址为R1+R2的存储单元中,
并将新地址R1+R2写入R1
STRR0,[R1,#8]!
;将R0字数据存入存储器地址为R1+8的存储单元中,
并将新地址R1+8写入R1
STRR0,[R1,R2,LSL#2]!
;将R0字数据存入地址为R1+R2*4的存储单元中,
并将新地址R1+R2*4写入R1
LDRR0,[R1],#8;将存储器地址为R1的字数据读入寄存器R0,
并将新地址R1+8写入R1
LDRR0,[R1],R2;将存储器地址为R1的字数据读入寄存器R0,
并将新地址R1+R2写入R1
LDRR0,[R1],R2,LSL#2;将存储器地址为R1的字数据读入寄存器R0,
并将新地址R1+R2*4写入R1
【备注】注意事项:
a、立即数绝对值不大于4095的数值,可使用带符号数,即在-4095~+4095之间。
(4096D=1000H)
b、语句的标号不能指向程序存储器的程序存储区,而是指向程序存储器的数据存储区或数据存储器的数据存储区。
另外指向的区域是可修改的。
例如,在用户模式下,有些存储区是不能访问的或是只读的。
c、字传送时,偏移量必须保证偏移的结果能够使地址对齐。
d、使用寄存器移位的方法计算偏移量时。
移位的位数不能超过规定的数值,而且不能用寄存器表示移位的位数。
各类移位指令的移位位数规定如下:
ASR#n:
算术右移(1≤n≤32)
LSL#n:
逻辑左移(0≤n≤31)
LSR#n:
逻辑右移(1≤n≤32)
ROR#n:
循环右移(1≤n≤31)
e、R15作为基址寄存器Rn时,不可以使用回写功能,即使用后缀“!
”,另外,R15不可作为偏移寄存器使用。
5、字节数据加载/存储指令:
LDRB/STRB
LDRB指令用于从存储器中将一个8位字节的数据加载到目的寄存器,同时将寄存器的高24位清零。
该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。
当程序计数器PC作为目的寄存器时,指令从存储器读取的数据被当做目的地,从而可以实现程序流程的跳转
STRB指令用于从源寄存器中将一个8位的字节数据存储到存储器中,该字节数据为源寄存器的低8位,STRB指令和LDRB指令的区别在于数据的传送方向。
LDRBR0,[R1];将存储器地址为R1的字节数据读入寄存器R0,
并将R0的高24位清零。
LDRBR0,[R1,#8];将存储器地址为R1+8的字节数据读入寄存器R0,
并将R0的高24位清零。
STRBR0,[R1];将寄存器R0中的字节数据写入以R1为地址的存储器中。
STRBR0,[R1,#8];将寄存器R0中的字节数据写入以R1+8为地址的存储器中。
6、LDRH/STRH半字数据加载/存储指令
31~28| 27~25| 24232221 20 |19~16| 15~12| 11~8 |7 6 5 4 |3~0
cond | 000 | P U I W L |Rn | Rd| addr_H |1S H 1|addr_L
cond:
指令执行的条件编码
I、P、U、W:
用于区别不同的地址模式(偏移量)。
I为0时,偏移量为8位立即数,I为1时,偏移量为寄存器移位。
P表示前/后变址,U表示加/减,W表示回写。
L:
L为1表示加载,L为0表示存储。
S:
用于区别有符号访问(S为1)和无符号访问(S为0)
H:
用于区别半字访问(H为1)或字节访问(H为0)
Rd:
源/目标寄存器
Rn:
基址寄存器
addr H/addr I:
表示偏移量,I为0时,偏移量为8位立即数由addr H和addr I组成;
I为1时,偏移量为寄存器移位addr H为0,addr L表示寄存器编号
LDR指令用于从寄存器中间一个16位的半字数据加载到目的寄存器Rd中,同时将寄存器的高16位清零,该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。
当程序计数器PC作为目的寄存器时,指令从存储器中读取的数据被当做目的地址,从而可以实现程序流程的跳转。
LDRHR0,[R1];将存储器地址R1的半字数据读入寄存器R0,
并将R0的高16位清零
LDRHR0,[R1,#8];将存储器地址为R1+8的半字数据读入寄存器R0,
并将R0的高16位清零
LDRHR0,[R1,R2];将存储器地址为R1+R2的半字数据读入寄存器R0,
并将R0的高16位清零
STRHR0,[R1];将寄存器R0中的半字数据写入以R1为地址的存储器中
使用半字加载/存储指令需要注意的事项:
(1)必须半字地址对齐。
(2)对于R15的使用需要慎重,R15作为基址寄存器Rn时,不可以使用回写功能,不可使用R15作为目的寄存器。
(3)立即数偏移使用的是8位无符号数。
(4)不能使用寄存器移位寻址
7、有符号数字节/半字加载指令:
LDRSB/LDRSH
LDRSB指令用于从存储器中间一个8位的字节数据加载到目的寄存器中,同时将寄存器的高24位设置为该字节数据的符号位的值,即将该8位字节数据进行符号位的扩展,生成32位数据;LDRSH指令用于从存储器中将一个16位的半字数据加载到目的寄存器Rd中,同时将寄存器的高16位设置为该字数据的符号位的值,即将该16位字数据进行符号位的扩展,生成32位数据。
LDRSBR0,[R1,#4];将存储地址为R1+4的有符号字节数据读入R0,
R0中的高24位设置为高字节数据的符号位
LDRSHR6,[R2],#2;将存储地址为R2+2的有符号半字数据读入R6,
R6的高16位设置成该字节数据的符号位,R2=R2+2
8、多寄存器加载和存储指令:
LDM/STM
LDM指令用于从基址寄存器所指示的一片连续存储器中读取数据到寄存器列表所指示的多个寄存器中,内存单元的其实地址为基址寄存器Rn的值,各个寄存器有寄存器列表regs表示。
该指令一般用于多个寄存器数据的出栈操作;STM指令用于将寄存器列表所指示的多个寄存器的值存入到由基址寄存器所指示的一片连续存储器中,内存单元的其实地址为基址寄存器Rn的值,各个寄存器由寄存器列表regs表示。
指令的其它参数的用法和LDM指令是相同的。
该指令一般用于多个寄存器数据的进栈操作。
type类型。
用于数据的存储和读取有一下几种情况:
IA每次传送后地址值加
IB每次传送前地址值加
DA每次传送后地址值减
DB每次传送前地址值减
对于堆栈操作有如下几种情况:
FD满递减堆栈
ED空递减堆栈
FA满递增堆栈
EA满递增堆栈
{!
}为可选后缀,若选用该后缀,则当数据加载与存储完毕后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。
{^}为可选后缀,当治疗为LDM且寄存器列表中包含R15,选用该后缀时表示:
除了正常数据加载和存储之外,还将SPSR复制到CPSR。
同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
LDMIAR0!
,{R6-R8};R6<-[R0],R7<-[R0+4],R8<-[R0+8],R0<-R0+12
LDMIBR0!
,{R6-R8};R6<