ARM寻址方式及相关指令汇总

1、寻址方式

所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式。

(1)立即寻址也叫立即数寻址,这是一种特殊的寻址方式,操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数,对应的寻址方式也就叫做立即寻址。例如以下指令:

ADD R0,R0,#1 ;R0←R0+1
ADD R0,R0,#0x3f ;R0←R0+0x3f
在以上两条指令中,第二个源操作数即为立即数,要求以“#”为前缀,对于以十六进制表示的立即数,还要求在“#”后加上“0x”或“&”。

(2)寄存器寻址就是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。

ADD R0,R1,R2 ;R0←R1+R2
该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。

(3)寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。例如以下指令: 

ADD R0,R1,[R2] ;R0←R1+[R2]
LDR R0,[R1] ;R0←[R1]
在第一条指令中,以寄存器R2的值作为操作数的地址,在存储器中取得一个操作数后与R1相加,结果存入寄存器R0中。第二条指令将以R1的值为地址的存储器中的数据传送到R0中。

(4)基址变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址:

 LDR R0,[R1,#4] ;R0←[R1+4]
 LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4
 LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4
 LDR R0,[R1,R2] ;R0←[R1+R2]

2、ARM指令

(1)ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令:
 B 跳转指令
 BL 带返回的跳转指令
 BLX 带返回和状态切换的跳转指令
 BX 带状态切换的跳转指令

B 指令的格式为:B{条件} 目标地址
B指令是最简单的跳转指令。一旦遇到一个B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。
B Label
程序无条件跳转到标号Label处执行

CMP R1,#0
BEQ Label
当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行。

BL指令的格式为:BL{条件} 目标地址
BL 是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC当前值,因此,可以通过将R14 的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。
BL Label ;当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中

扫描二维码关注公众号,回复: 2806374 查看本文章

BLX指令的格式为:BLX 目标地址
BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切换。同时,子程序的返回可以通过将寄存器R14值复制到PC中来完成。

BX指令的格式为:BX{条件} 目标地址
BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。

(2)数据处理指令可分为数据传送指令、算术逻辑运算指令和比较指令等。数据传送指令用于在寄存器和存储器之间进行数据的双向传输。

算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR中的相应条件标志位

MOV指令的格式为:MOV{条件}{S} 目的寄存器,源操作数
MOV指令完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。指令示例:

 MOV R1,R0 ;将寄存器R0的值传送到寄存器R1
 MOV PC,R14 ;将寄存器R14的值传送到PC,常用于子程序返回
 MOV R1,R0,LSL#3 ;将寄存器R0的值左移3位后传送到R1
MVN指令的格式为:MVN{条件}{S} 目的寄存器,源操作数
MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MOV指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。
MVN R0,#0xff ;R0<=0xffffff00
CMP{条件} 操作数1,操作数2
CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。标志位表示的是操作数1与操作数2的关系(大、小、相等),例如,当操作数1大于操作操作数2,则此后的有GT 后缀的指令将可以执行。指令示例:
 CMP R1,R0 ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
 CMP R1,#100 ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位
ADD{条件}{S} 目的寄存器,操作数1,操作数2
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
指令示例:
 ADD R0,R1,R2 ; R0 = R1 + R2
 ADD R0,R1,#256 ; R0 = R1 + 256
 ADD R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)
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)
AND{条件}{S} 目的寄存器,操作数1,操作数2
AND指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该
指令常用于屏蔽操作数1的某些位。
AND R0,R0,#3 ; 该指令保持R0的0、1位,其余位清零
ORR{条件}{S} 目的寄存器,操作数1,操作数2
ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数1的某些位。
ORR R0,R0,#3 ; 该指令设置R0的0、1位,其余位保持不变
TST{条件} 操作数1,操作数2
TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。操作数1是要测试的数据,而操作数2是一个位掩码,根据测试结果设置相应标志位。当位与结果为0时,EQ位被设置。
指令示例:
 TST R1,#%1 ;用于测试在寄存器R1中是否设置了最低位(%表示二进制数)。
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中的相关条件标志位
LDR指令的格式为:LDR{条件} 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理 
 LDR R0,[R1]将存储器地址为R1的字数据读入寄存器R0。
 LDR R0,[R1,R2]将存储器地址为R1+R2的字数据读入寄存器R0。
 LDR R0,[R1,#8]将存储器地址为R1+8的字数据读入寄存器R0。
 LDR R0,[R1,R2] !将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1
LDRB指令的格式为:LDR{条件}B 目的寄存器,<存储器地址>
LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。指令示例: 
 LDRB R0,[R1] ;将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。
 LDRB R0,[R1,#8] ;将存储器地址为R1+8的字节数据读入寄存器R0,并将R0的高24位清零
LDRH指令的格式为:LDR{条件}H 目的寄存器,<存储器地址>
LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对
数据进行处理。指令示例:
 LDRH R0,[R1] ;将存储器地址为R1的半字数据读入寄存器R0,并将R0的高16位清零。
 LDRH R0,[R1,R2] ;将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零
STR指令的格式为:STR{条件} 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。指令示例:
 STRR0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
 STRR0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中
SWP指令的格式为:SWP{条件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用于将源寄存器2所指向的存储器中的字数据传送到目的寄存器中,同时将源寄存器1中的字数据传送到源寄存器2所指向的存储器中。显然,当源寄存器1和目的寄存器为同一个寄存器时,指令交换该寄存器和存储器的内容。指令示例: 
 SWP R0,R1,[R2];将R2所指向的存储器中的字数据传送到R0,同时将R1中的字数据传送到R2所指向的存储单元
 SWP R0,R0,[R1];该指令完成将R1所指向的存储器中的字数据与R0中的字数据交换

ARM微处理器支持数据的移位操作,移位操作在ARM指令集中不作为单独的指令使用,它只能作为指令格式中是一个字段,在汇编语言中表示为指令中的选项。移位操作包括如下6种类型,ASL和LSL是等价的,可以自由互换:

 LSL 逻辑左移
 ASL 算术左移
 LSR 逻辑右移
 ASR 算术右移
 ROR 循环右移
LSL操作的格式为:通用寄存器,LSL操作数
LSL可完成对通用寄存器中的内容进行逻辑左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。操作示例:
MOV R0, R1, LSL#2 将R1中的内容左移两位后传送到R0中
ROR操作的格式为:通用寄存器,ROR 操作数
ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。显然,当进行32位的循环右移操作时,通用寄存器中的值不改变。操作示例:
MOV R0, R1, ROR#2  将R1中的内容循环右移两位后传送到R0中

常见指令介绍:

LR就是连接寄存器(Link Register, LR).在ARM体系结构中LR的特殊用途有两种:
一是用来保存子程序返回地址;
二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
通常LR就是各异常模式下的R14

LR --- Link Register 连接寄存器

PC ---Program Counter, 程序计数器, 是 各种模式下的 R15

SP --- Stack Pointer 堆栈指针, 也就是各异常模式下的R13.

CPSR --- Current Program Status Register 程序状态寄存器.

SPSR --- Saved Program Status Register 备份状态寄存器, 当异常发生时,SPSR用来保存CPSR的当前值,从异常退出后,可由SPSR来恢复CPSR

功能介绍:

1、堆栈指针r13(SP):每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性。

2、连接寄存器r14(LR):每种模式下r14都有自身版组,它有两个特殊功能。

    (1)保存子程序返回地址。使用BL或BLX时,跳转指令自动把返回地址放入r14中;子程序通过把r14复制到PC来实现返回,通常用下列指令之一:
                        MOV PC, LR 
                        BX LR

    通常子程序这样写,保证了子程序中还可以调用子程序。
                         stmfd sp!, {lr}
                         ……
                         ldmfd sp!, {pc}

    (2)当异常发生时,异常模式的r14用来保存异常返回地址,将r14如栈可以处理嵌套中断。

3、程序计数器r15(PC):PC是有读写限制的。当没有超过读取限制的时候,读取的值是指令的地址加上8个字节,由于ARM指令总是以字对齐的,故bit[1:0]总是00。当用str或stm存储PC的时候,偏移量有可能是8或12等其它值。在V3及以下版本中,写入bit[1:0]的值将被忽略,而在V4及以上版本写入r15的bit[1:0]必须为00,否则后果不可预测。


更多ARM指令请参考:http://www.cnblogs.com/laojie4321/archive/2012/04/05/2433034.html

ARM反汇编介绍:http://blog.chinaunix.net/uid-25871104-id-2938389.html

汇编实例:http://www.rosoo.net/a/201006/9706.html

命令介绍:http://general.blog.51cto.com/927298/657803

介绍:http://www.docin.com/p-736866302.html

http://futongrui.blog.sohu.com/133056091.html

猜你喜欢

转载自blog.csdn.net/southcamel/article/details/9262547