内存访问和数据处理指令

ARM内存与数据处理指令详解

一、内存访问指令

1.2.LDR / STR

对于内存访问的指令有两个,一个是读 LDR:Load Register,一个是写 STR:Store Register。读指令的结构与其中的类型如下图所示:
在这里插入图片描述
写指令的结构与其类型:

在这里插入图片描述

MOV	R0, #0x20000
MOV R1, #0x10	
MOV	R2, #0x12
STR	R2, [R0]				;R2的值放在R0所示的地址
STR	R2, [R0, #4]			;R2的值放在R0+4所示的地址
STR	R2, [R0, #8]!			;R2的值放在R0+8所示的地址,感叹号是刷新了R0所存放的值,变成了0x20008
STR	R2, [R0, R1]			;R2的值放在R0+R1所示的地址
STR	R2, [R0, R1, LSL #4]	;R2的值放在R0+(R1<<4)所示的地址
STR	R2, [R0], #0x20			;R2的值放在R0所示的地址,R0=R0+0x20
MOV	R2, #0x34
STR	R2, [R0]				;R2的值放在R0所示地址
LDR	R3, [R0], +R1, LSL #1	;将R0+(R1<<1)所示地址上的值放在R3里

在这里插入图片描述

1.2. LDM / STM

这两个指令里面的字母 M 表示多个的意思,使用这类指令可以读取或写入多个值在寄存器列表中。

  • LDM:Load Multiple Register,下面是该指令的格式,Rn 是地址,其中 addr_mode 是说明该地址是增加还是减小、在变化之前读出数据或是在变化之后读出数据,这两个变数组成了四个搭配

在这里插入图片描述

  • STM:Store Multiple Register,与上面的同理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面举例验证一下,注意低标号的寄存器对应低地址

MOV		R1, #1
MOV		R2, #2
MOV		R3, #3
MOV		R0, #0x20000
STMDB	R0, {R1-R3}		;123依此存放在R0、R0-4、R0-8地址处,DB表示先减小指针,再

在这里插入图片描述
这样的情况是否似曾相识,这就是入栈的手段,根据栈指针指向,可分为满(Full)/空(Empty):

  • 满SP指向最后一个入栈的数据,需要先修改SP再入栈
  • 空SP指向下一个空位置,先入栈再修改SP

根据压栈时SP的增长方向,可分为增/减:

  • 增(Ascending):SP变大
  • 减(Descending):SP变小

组合后,就有4种方式:满增、满减、空增、空减。接下来是出入栈:

MOV		R1, #1
MOV		R2, #2
MOV		R3, #3
MOV		SP, #0x20000		;将指针指到0x20000上
STMFD	SP!, {R1-R3}		;123值按顺序压入栈,感叹号目的是刷新SP指针的地址,方便从该地址按顺序读入寄存器
MOV		R1, #0					;将这些寄存器清0,存放别的值
MOV		R2, #0
MOV		R3, #0
LDMFD	SP!, {R1-R3}		;读到寄存器之后,SP的值又回到0x20000

常用的“满减”:

  • 入栈时用STMDB,也可以用STMFD,作用一样
  • 出栈时用LDMIA,也可以用LDMFD,作用一样

在这里插入图片描述

二、数据处理指令

加法指令ADD:

ADD  R1, R2, R3         ;R1 = R2 + R3
ADD  R1, R2, #0x12      ;R1 = R2 + 0x12

减法指令SUB:

SUB  R1, R2, R3         ;R1 = R2 - R3
SUB  R1, R2, #0x12   	;R1 = R2 - 0x12

位操作:

AND R1, R2, #(1<<4)  		  ;位与,R1 = R2 & (1<<4)
AND  R1, R2, R3        	      ;位与,R1 = R2 & R3
BIC  R1, R2, #(1<<4)  		  ;清除某位,R1 = R2 & ~(1<<4)
BIC  R1, R2, R3            	  ;清除某位,R1 = R2 & ~R3
ORR   R1, R2, R3			  ;设置某位,R1 = R2 | R3

比较:

CMP R0, R1                	;比较R0-R1的结果
CMP R0, #0x12            	;比较R0-0x12的结果
TST  R0, R1                 ;测试 R0 & R1的结果
TST  R0, #(1<<4)        	;测试 R0 & (1<<4)的结果

比较出的结果能影响到程序状态寄存器的位,下图是程序状态寄存器位域的意义:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、跳转指令

核心指令是B、BL:

  • B:Branch,跳转
  • BL:Branch with Link,跳转前先把返回地址保持在LR寄存器中
  • BX:Branch and eXchange,根据跳转地址的 BIT0 切换为 ARM 或 Thumb 状态 (0:ARM状态,1:Thumb状态)
  • BLX:Branch with Link and eXchange 根据跳转地址的BIT0切换为ARM或Thumb状态 (0:ARM状态,1:Thumb状态)

编写一个简单的延迟函数,倒数 5 个数,倒数结束后返回 LR 寄存器所保存的地址,使用 BL 的时候,LR 寄存器会保存跳转前下一行代码的地址,也就是 MOV R0, #1

		BL		Delay
		MOV		R0, #1
Delay
		MOV		R0, #5
Loop
		SUBS		R0, R0, #1
		BNE		Loop
		MOV		PC, LR

不使用 BL 指令也可以做到相同效果,将 Ret 地址保存到 LR 寄存器里,再将 Delay 地址保存到 PC 寄存器里,PC 地址首先会指到 Delay 函数并运行,最后将 LR 的地址赋给 PC 寄存器,运行MOV R0, #1

		ADR		LR, Ret
		ADR		PC, Delay
Ret
		MOV		R0, #1
Delay
		MOV		R0, #5
Loop
		SUBS		R0, R0, #1
		BNE		Loop
		MOV		PC, LR
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值