ARM处理器的指令集
一、数据处理类指令
数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作,所以ARM数据处理指令均可以选择使用S后缀,以影响状态标志位。
影响状态标志位的命令:
MOVS–>数据传送指令(只能用在寄存器和寄存器之间)
MVNS–>数据传送指令(和mov区别是,不仅进行数据传输,还进行数据取反)
ADDS–>加法指令
SUBS–>减法指令
MULS–>乘法指令
ANDS–>逻辑与指令(相同是1,不同是0,区别“按位与TST"指令)
ORRS–>逻辑或指令(不同是0,相同是1,区别“按位与TST"指令)
BICS–>设置某一位为1
CMP–>比较指令
TST–>安位与指令
1.数据传送指令
用于操作数传送到目的寄存器中。
MOV R1,R0 ;将寄存器R0的值传送到寄存器R1中。
MVN R0,#0 ;将立即数0按位取反传送到寄存器R0中。
可以在MOV和MVN后面加S,S会改变CPSR的值,不加就不会改变。
2.比较指令
用于对2个操作数进行比较,同时更新CPSR中的条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。
CMP R1,R0 ;将R1的值与R0的值相减,并更新结果CPSR的标志位,不用加S
CMN R1,#100 ;取反后相减进行比较,即将R1的值与立即数100相加,并设置标志位
3.测试指令
用于对2个操作数进行按位的与运算,并根据运算结果更新CPSR中的标志位。
TST R1,#%1 ;将R1的值与二进制1按位与运算,并改变标志位。
TEQ R1,R2 ;将R1的值与R2的值按位异或,并设置标志位,通常用来比较两个操作数的是否相等。可以看Z位,如果为Z位是1,那就相等,不是1,就不相等。
4.加法指令
用于将2个操作相加,并将结果存放到目的寄存器中,需要三个参数。
ADD R0,R1,R2 ;R1+R2=R0,操作数1+操作数2
ADC R0,R1,R2 ;R1+R2+进位数=R0
例:
MOV R0,#0Xffffffff ;0xffffffff→R0 R0=0xffffffff
ADDS R0,R0,#0xffffffff ;R0=R0+0xffffffff R0=0xfffffffe,不考虑进位
ADCS R0,R0,#0xffffffff ;R0=R0+0xffffffff+进位数 R0=0xfffffff,进位标识符位C=1,R0最后还要加1
5.减法指令
用于操作数1减操作数2,并将结果存放到目的寄存器中。注意在访问CPSR时设置后缀S。
SUB R0,R1,R2 ;R0=R1-R2
SBC R0,R1,R2 ;R0=R1-R2-!C 操作数1减操作数2,再减去标志位C位的反码。
RSB R0,R1,R2 ;R0=R2-R1
RSC R0,R1,R2 ;R0=R2-R1-!C
6.逻辑运算指令
对两个操作数进行逻辑与运算,并把结果放在目的寄存器中。
AND R0,R0,#3 ;保证R0的0,1位不变,其他位为0。考虑到“与”的运算法则全1为1,其余为0。
ORR R0,R0,#3;运用“或”的准则,改变R0的0,1位,其余为不变。
EOR R0,R0,#3;异或指令,运用异或的运算法则,反转R0的0,1位,其余不变。通常用于取反某一位的值,并保证其他为不变。
BIC R0,R0,#0xB;位清除指令,清除R0中的0,1,3位,其余为保持不变。原理是0xB先按位取反,然后与R0相与。主要用于清除某一位的值。
二、跳转指令
跳转指令主要用于实现程序流程的跳转,比如函数调用,发生中端等情况都需要跳转指令。
BEQ Label ;带条件的跳转,当Z置位,即结果为0时,跳转到Label。
BX R0 ;带状态切换的跳转指令,切换到以R0为地址的Thumb指令。
BL Label;无条件跳转到标号为 Label处执行,同时将PC的值保存到R14中。
BLX Label ;带返回且带状态切换的转移指令。
三、乘法指令
完成操作数1和操作数2的乘法运算,并把结果放置到目的寄存器。如果要改变CPSR的值,就需要加后缀S。
MUL R0,R1,R2 ;R0=R1XR2
MLA R0,R1,R2,R3 ;R0=R1XR2+R3
SMULL/UMULL R0,R1,R2,R3 ;R0=(R2XR3)的低32位,R1=(R2XR3)的高32位
四、LoadStore指令
ARM微处理器中的加载/存储指令,用于在寄存器和存储器之间传送数据。说直接就是把存取器的数据取出来放在寄存器中或把寄存器的数据保存到存储器中。
1.单数据加载/存储指令
在单个存储器中传送数据。
LDR R0,[R1] ;将存储器地址为R1的字数据读入到寄存器R0。
LDR R0,[R1+R2] ;将存储器地址为R1+R2的字数据读入到寄存器R0。
STR R0,[R1],#8;将R0的数据写到R1为地址的存储器,并让R1=R1+8
2.批量数据加载/存储指令
在多个存储器单元之间传送数据。
语法格式:LDM{条件}{类型}基址寄存器{!},寄存器列表{^}
{类型}为可选后缀,通常有以下几种情况:
(1)数据块操作:
- IA:每次传送后的地址加4
- DA:每次传送后的地址减4
- IB:每次传送前的地址加4
- DB:每次传送前的地址减4
(2)堆栈操作:
- FD:满递减堆栈
- FA:满递增堆栈
- ED:空递减堆栈
- EA:空递增堆栈
{!}:对操作后地址进行更新。
STM和LDM操作对多个寄存器与存储器之间的数据操作。
例如:
(1)数据块操作:
总结:对数据块操作时,存取与类型匹配共有8种结果,对应处理就可以了
(2)堆栈操作:
总结:对堆栈操作,STM存数据时与数据块相对应。LDM取数据时,与STM相反。
如果我们想要先将数据存进去,然后又按照原来的顺序取出来,我们可以通过这种操作两两匹配。
例如:
先采用对数据块操作模式:
存:STMIA R0,{R1,R2}
取:LDMIA R0,{R1,R2}
理论来说,是可以达到目的的,但地址不更新,可能会造成后续的数据把前面的数据覆盖了。所以我们一般需要进行地址更新。
存:STMIA R0!,{R1,R2}
取:LDMDB R0!,{R1,R2}
这种模式取反就可以实现存取数据的操作了。
对堆栈操作:
存:STMFD R13!,{R1,R2}
取:LDMFD R13!,{R1,R2}
因为LDM对应的与STM相反,所以在取反,就相同了,因此对堆栈的操作的存取模式是一样的。