概述
一、ARM寄存器
ARM寄存器分为2类,普通寄存器和状态寄存器。普通寄存器总共16个,分别为R0-R15;状态寄存器共2个,分别为CPSR和SPSR。
R15别名PC(program counter),中文称为程序计数器,保存当前正在执行的指令在内存中的地址,当指令执行结束后,PC的值自动+1,即自动指向下一条即将执行的指令在内存中的位置。因为当程序通过汇编指令完成了对PC寄存器的赋值操作的时候,其实就是完成了一次无条件跳转。
R14别名LR(linked register),中文称为链接寄存器,用于存放子程序的返回地址,它是ARM程序实现子程序调用的关键所在。用一个C程序举例。
int main(void){
addsub(5);
int i = 8;
}
int addsub(int a){
int c = 3;
return c;
}
对于上面的程序,编译器会将第2行编译为BL addsub;BL addsub会完成两件事情:1、将子程序的返回地址(也就是第3行代码在内存中的位置)保存到寄存器LR中;2、跳转到子程序addsub的第1条指令处。编译器将第8行编译为:MOV PC, LR;这样保存在LR中的返回地址赋给PC,完成了从子程序的返回。由此可见,LR是用于存放子程序的返回地址的。
R13别名SP(stack pointer),中文名称栈指针寄存器。顾名思义,它是用于存放堆栈的栈顶地址的。每次当我们进行出栈和入栈的时候,都将根据该寄存器的值来决定访问内存的位置(即:出入栈的内存位置),同时在出栈和入栈操作完成后,SP寄存器的值也应该相应增加或减少。
寄存器R0-R12是普通的数据寄存器,可用于任何地方。
状态寄存器CPSRcurrent program status register),中文名称:当前程序状态寄存器,顾名思义它是用于保存程序的当前状态的。
上图是CPSR寄存器的构成,我主要介绍下条件代码标志位,它们是ARM指令条件执行的依据。
N:当用两个补码表示的带符号数进行运算时,N=1表示运算的结果为负数;N=0表示运算的结果为正数或零
Z:Z=1表示运算的结果为零,Z=0表示运算的结果非零。
C:可以有4种方法设置C的值:
-加法运算(包括CMP):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0。
-减法运算(包括CMP):当运算时产生了借位时(无符号数溢出),C=0,否则C=1。
-对于包含移位操作的非加/减运算指令,C为移出值的最后一位。
-对于其它的非加/减运算指令,C的值通常不会改变。
V:可以有2种方法设置V的值:
-对于加减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出
-对于其它的非加/减运算指令,V的值通常不会改变。
Q:在ARM V5及以上版本的E系列处理器中,用Q标志位指示增强的DSP运算指令是否发生了溢出。在其它版本的处理器中,Q标志位无定义
二、ARM常用指令和伪指令
ARM常用指令并不太多,因此使用阅读ARM汇编代码并不太困难。以下是使用频率最高的指令和伪指令:
B,BL;MOV,MVN;CMP;LDR,STR;ADD,SUB,ADC,SBC,MUL;AND,ORR,XOR,TST,BIC;LDM/STM;NOP
1、跳转语句 B,BL
B指令(Branch)表示直接向程序计数器PC写入跳转地址值,改变PC的值实现程序跳转,就如同MOV PC,LR;
B Label ;程序无条件跳转到标号Label处执行。
BL指令(Branch with Link)表示带返回值的跳转.。跳转之前会在寄存器R14(LR)中保存PC的当前内容,因此,可以通过将R14的内容重新加载到PC中,返回到BL指令的下个指令处执行。该指令是实现子程序调用的一个基本且常用的手段。
2、传输数据指令MOV,MVN
MOV指令比较简单,用三个示例来说明。
MOV R1,R0 ; 将寄存器R0的值传送到寄存器R1
MOV PC,R14 ; 将寄存器R14的值传送到 PC,常用于子程序返回
MOV R1,R0,LSL#3 ; 将寄存器R0的值左移3位后传送到R1
MVN( MOVE Negative)取反后再传值,比MOV多了一步取反
MVN R0, #0 ;把0取反(即-1)传给R0
MVN R1,R2 ;把R2的值取反传给R1
3. 比较指令CMP,CMN
CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。
CMP R1,R0 ; 将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100 ; 将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位
CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较,同时更新CPSR中条件标志位的值。该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。
4. 加载/存储指令LDR,STR
LDR{条件} 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为 目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0
STR{条件} 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中,是LDR的逆操作。 该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
STR R0,[R1] ; 把R0的值,存入到R1对应地址空间上(*R1 = R0)
STR R0,=0x30008000 ;把R0中值存入到地址0x30008000
5. 算术运算指令ADD/ADC,SUB/SBC,MUL
ADD{条件}{S} 目的寄存器,操作数1,操作数2
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
ADD R0,R1,R2 ; R0 = R1 + R2
ADD R0,R1,#256 ; R0 = R1 + 256
ADC{条件}{S} 目的寄存器,操作数1,操作数2
ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。它使用一个进位标志位,这样就可以做比32位大的数 的加法,注意不要忘记设置S后缀来更改进位标志。操作数1应是一个寄存器,操作数2可以是一 个寄存器,被移位的寄存器,或一个立即数。
ADDS R0,R4,R8 ; 加低端的字
ADCS R1,R5,R9 ; 加第二个字,带进位
ADCS R2,R6,R10 ; 加第三个字,带进位
ADC R3,R7,R11 ; 加第四个字,带进位
SUB指令的格式为:
SUB{条件}{S} 目的寄存器,操作数1,操作数2
SUB指令用于把操作数1减去操作数2,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即 数。该指令可用于有符号数或无符号数的减法运算。
SUB R0,R1,R2 ; R0 = R1 - R2
SUB R0,R1,#256 ; R0 = R1 - 256
SUB R0,R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
MUL{条件}{S} 目的寄存器,操作数1,操作数2
MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操 作数2均为32位的有符号数或无符号数。
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同时设置CPSR中的相关条件标志位
最后
以上就是鳗鱼便当为你收集整理的安卓ARM汇编知识整理(一)一、ARM寄存器二、ARM常用指令和伪指令的全部内容,希望文章能够帮你解决安卓ARM汇编知识整理(一)一、ARM寄存器二、ARM常用指令和伪指令所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复