ARM技术概论|ARM指令

ARM指令

1. ARM指令集

1.1 数据处理指令
助记符 操作 助记符 操作
MOV 数据传送 AND 逻辑与
MVN 数据取反传送 ORR 逻辑或
ADD EOR 逻辑异或
ADC 带进位的加 BIC 位清零
SUB CMP 比较
SBC 带借位的减 CMN 相反数比较
RSB 逆向减 TST 位测试
RSC 带借位逆向减 TEQ 测试相等
/*****数据处理指令示例*****/
MOV		R0,	#0xFF		//R0 = 0xFF
MOV		R0,	R0			//R0 = R0...NOP指令
MOV		R0,	R0,	LSL#3	//R0 = R0 << 3
MOV		PC,	R14 		//退出到调用者,用于普通函数返回,PC即R15
MOVS	PC, R14 		//退出到调用者并恢复标志位,用于异常函数返回
MVN		R0, #4			//R0 = ~(4)
MVN		R0, #0			//R0 = ~(0)
ADD		R0, R1, R2		//R0 = R1 + R2
ADD		R0, R1, #0xFF	//R0 = R1 + 0xFF
ADD		R0, R2, R3, LSL#1	//R0 = R2 + (R3 << 1)
ADDS	R0, R4, R8			//加低端的字
ADCS	R1, R5, R9			//加下1个字,带进位
ADCS	R2, R6, R10 		//加第3个字,带进位
ADCS	R3, R7, R11 	 	//加高端的字,带进位
SUB		R0, R1, R2			//R0 = R1 - R2
SUB		R0, R1, #0xFF		//R0 = R1 - 0xFF
SUB		R0, R2, R3, LSL#1	//R0 = R2 - (R3 << 1)
SUBS	R0, R0, R2			//低位相减结果存储在R0,同时更新CPSR中对应的条件标志位
SBCS	R1, R1, R3			//高位相减同时减去低位的借位 R1 = R1 - R3 - (!C)
RSB		R2, R0, #0xFF		//R2 = 0xFF - R0
RSBS	R2, R0, #0			//
RSC		R3, R1, #0			//
AND		R0, R0, #0x03		//R0寄存器的0、1位不变,其他位清零
AND		R2, R1, R3			//R2 = R1 & R3
AND		R0, R0, #0x01		//R0 = R0 & 0x01
ORR		R0, R0, #0x03		//R0寄存器的0、1位设置为1
ORR		R0, R0, #0x0F		//R0寄存器的低4位设置为1
EOR		R0, R0, #0x03		//反转R0中的第0和1位
EOR		R1, R1, #0x0F		//将R1的低4位取反
EOR		R2, R1, R0			//R2 = R1 ^ R0
EORS	R0, R5, #0x01		//将R5和0x01进行逻辑异或,结果保存到R0,并根据执行结果更新标志位
BIC		R0, R0, #0x1011		//清除R0中的位0、1和3,保持其余的不变
BIC		R1, R2, R3			//将R3的反码和R2逻辑与,结果保存到R1中
CMP		R1, #10				//比较R1和立即数10并更新相关的标志位
CMP		R1, R2				//比较R1和R2中的值并设置相关的标志位
CMN		R0, #1				//
TST		R0, #1				//测试R0的最低位是否为0
TEQ		R0, R1				//比较R0和R1是否相等,不影响CPSR中的V位和C位
1.2 乘法指令
助记符 操作 助记符 操作
MUL 乘(保留32位结果) UMLAL 无符号数长乘–累加
MLA 乘(32位结果) SMULL 有符号数长乘
UMULL 无符号数长乘 SMLAL 有符号数长乘–累加
/***** 乘法指令示例*****/
MUL		R1, R2, R3			//R0 = R2 * R3
MULS	R0, R3, R7			//R0 = R3 * R7,并根据运算结果更新CPSR中的N位和Z位
MLA		R1, R2, R3, R0		//R1 = R2*R3 + R0
UMULL	R0, R1, R5, R8		//R0 = R5*R8[31:0];  R1 = R5*R8[63:32]
UMLAL	R0, R1, R5, R8		//R0 = R5*R8[31:0] + R0;  R1 = R5*R8[63:32] + R1
SMULL	R2, R3, R7, R6		//R2 = (R7*R6)[31:0];  R3 = (R7*R6)[63:32]
SMLAL	R2, R3, R7, R6		//R2 = (R7*R6)[31:0] + R2;  R3 = (R7*R6)[63:32] + R3
1.3 跳转指令
助记符 操作 助记符 操作
B 跳转 BL 带返回的连接跳转
BX 跳转并切换状态 BLX 带返回的跳转并切换状态
/***** 跳转指令示例*****/
B		LABLE		//跳转到LABLE标号处
B		0x1234		//跳转到绝对地址0x1234处
BL		func		//跳转到子程序func处执行
BX		R14			//从Thumb状态返回到ARM状态
1.4 Load/Store指令
  • 单寄存器的Load/Store指令
助记符 操作 助记符 操作
LDR 把存储器中的一个字装入寄存器 LDRBT 用户模式下将一个字节装入寄存器
STR 将寄存器中的字保存到存储器 STRBT 用户模式下将寄存器中的低8位字节保存到存储器
LDRB 把一个字节装入一个寄存器 LDRT 用户模式下把一个字装入寄存器
STRB 将寄存器中的低8位字节保存到存储器 STRT 用户模式下将存储器中的字保存到寄存器
LDRH 把一个半字装入一个寄存器 LDRSB 把一个有符号字节装入寄存器
STRH 将寄存器中的低16位半字保存到存储器 LDRSH 把一个有符号半字装入寄存器
/***** 单寄存器的Load/Store指令示例*****/
LDR		R1, [R0, #0x12]			//将R0+0x12地址处的数据读出,保存到R1中
LDR		R1, [R0, R2, LSL#2]		//将R0+(R2<<2)地址处的数据读出,保存到R1中
LDR		Rd, [Rn], #0x04			//Rn地址中的数据传送到Rd,传送完成后Rn=Rn+0x04
STR		R1,	[R0]				//保存变量
  • 多寄存器的Load/Store指令
助记符 操作 助记符 操作
LDM 装载多个寄存器 STM 保存多个寄存器
/*****多寄存器的Load/Store指令示例*****/
LDMIA		R0!, {
    
    R3~R9}			//加载R0指向的地址上的多字数据,保存到R3~R9中,R0值更新
STMIA		R1!, {
    
    R3~R9}			//将R3~R9的数据存储到R1指向的地址上,R1值更新
STMFD		SP!, {
    
    R0~R7, LR}		//现场保存,将R0~R7,LR入栈
LDMFD		SP!, {
    
    R0~R7, PC} ^		//恢复现场,异常处理返回,同时恢复SPSR中的值到CPSR
  • 单数据交换指令
助记符 操作 助记符 操作
SWP 字交换 SWPB 字节交换
/*****单数据交换指令示例*****/
SWP		R1, R1, [R0]		//将R1的内容与R0指向的存储单元内容进行交换
SWPB	R1, R2, [R0]		//将R0指向的存储单元内容读取一字节数据到R1中,在将R2寄存器中的数据存储到R0指向的内存单元中
1.5 状态寄存器传输指令
助记符 操作 助记符 操作
MRS 把程序状态寄存器(PSR)的值送到通用寄存器 MSR 把通用寄存器的值送到PSR或把一个立即数送到PSR
/*****状态寄存器传输指令示例*****/
MRS		R1, CPSR		//将CPSR状态寄存器读出,保存到R1中
MRS		R2, SPSR		//将SPSR状态寄存器读出,保存到R2中
MSR		CPSR_c, 0xD3	//CPSR[7:0] = 0xD3, 切换到管理模式
MSR		CPSR_cxsf, R3	//CPSR = R3
1.6 协处理指令
助记符 操作 助记符 操作
CDP 协处理器数据操作 MRC 从协处理器寄存器传数据到ARM寄存器
LDC 装载协处理器寄存器 STC 存储协处理器寄存器
MCR 从ARM寄存器传数据到协处理器寄存器
1.7 异常产生指令
助记符 操作 助记符 操作
SWI 软中断指令 BKPT 断点中断指令
/*****异常产生指令示例*****/
SWI		0			//产生软中断,中断立即数为0
SWI		0x123456	//产生软中断,中断立即数为0x123456

2. ARM指令的寻址方式

2.1 数据处理指令操作数的寻址方式

ARM数据处理指令的基本语法格式如下示:

<opcode> {<cond>} {S} <Rd>, <Rn>, <shifter_operand>

  • 立即数寻址:指令中的第二操作数<shifter_operand>是立即数
/*****立即数寻址示例*****/
//下面是一些应用立即数的指令
MOV		R0, #0			 //送0到R0
ADD		R3, R3, #1		 //R3的值加1
CMP		R7, #1000		 //R7的值和1000比较
BIC		R9, R8, #0xff00	 //将R8中8~15位清零,结果保存在R9中
  • 寄存器寻址:指令中的第二操作数<shifter_operand>是寄存器中的值
/*****寄存器寻址示例*****/
MOV		R2, R0			//R0的值送R2
ADD		R4, R3, R2		//R2加R3,结果送R4
CMP		R7, R8			//比较R7和R8的值
  • 寄存器移位寻址:指令中的第二操作数<shifter_operand>是由寄存器中的值移位得到
/*****寄存器移位寻址示例*****/
//下面是使用移位操作的例子
ADD		R2, R0, R1, LSR#5
MOV		R1, R0, LSL#1
RSB		R9, R5, R5, LSL#1
2.2 字及无符号字节的Load/Store指令的寻址方式
  • 寄存器间接寻址:将地址放在一个通用寄存器中,即所需要的操作数保存在寄存器指定地址的存储单元中,即寄存器中的值为操作数的地址指针。寄存器间接寻址字及无符号字节的Load/Store指令语法格式如下示:

LDR|STR {<cond>} {B} {T} <Rd>, [Rm]

/*****寄存器间接寻址示例*****/
LDR		R1, [R2]	//将R2中的数值作为地址,取出此地址中的数据保存在R1中
STR		R1, [R2]	//将R2中的数值作为地址,取出R1中的值存入R2所指向的地址
  • 基址变址寻址:是将基地址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。基址变址寻址的Load/Store指令语法格式如下示

LDR|STR {<cond>} {B} {T} <Rd>, [Rm, ±<addressing_mode>]

/*****基址变址寻址示例*****/
LDR		R1, [R0, #0x0f]		//将R0中的数值加0x0f作为地址,取出此地址的数值保存在R1中
STR		R1, [R0, #-2]		//将R0中的数值减2作为地址,把R1中的内容保存到此地址位置
STR		R1, [R0, +R2]		//将R0的值加上R2的值作为地址,把R1的内容保存在该地址中
2.3 批量Load/Store指令的寻址方式
  • 多寄存器/块拷贝寻址:将一片连续内存单元的数据加载到通用寄存器组中或将一组通用寄存器的数据存储到连续的内存单元中。该类的指令语法格式如下示:

LDM|STM {<cond>} <addressing_mode> <Rn> { ! }, < registers/>< ^/>

/*****多寄存器/块拷贝寻址示例*****/
STMIA	R0!, {
    
    R1-R7}	//将R1~R7的数据保存到R0所指向的存储器中,R0的值之后增加,增长方向为向上增长,类似于C语言中的i++
STMIB	RO!, {
    
    R1-R7}	//R0的值先增加,后将R1~R7的数据保存到R0所指向的存储器中,增长方向为向上增长,类似于C语言中的++i
STMDA	R0!, {
    
    R1-R7}	//将R1~R7的数据保存到R0所指向的存储器中,R0的值之后减少,增长方向为向下增长,类似于C语言中的i--
STMDB	RO!, {
    
    R1-R7}	//R0的值先减少,后将R1~R7的数据保存到R0所指向的存储器中,增长方向为向下增长,类似于C语言中的--i
  • 堆栈操作寻址方式:对于堆栈的操作,数据写入内存和从内存中读出要使用不同的寻址模式,因为进栈操作和出栈操作要在不同的方向上调整堆栈操作

根据不同的寻址方式,堆栈可分为:Full栈、Empty栈、递减栈、递增栈
根据堆栈的不同种类,寻址方式可分为:满递减FD、空递减ED、满递增FA、空递增EA

2.4 相对寻址

相对寻址是基址寻址的一种变通,由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。有 B 和 BL 指令

/*****相对寻址示例*****/
BL	FUN1	//调用到FUN1子程序
B	LOOP	//条件跳转到LOOP标号处

猜你喜欢

转载自blog.csdn.net/Chuangke_Andy/article/details/108503284