ARM:特殊功能寄存器、Load/Store内存读写指令、栈操作指令

1.特殊功能寄存器读写指令

msr -->>将普通寄存器中的数据写到特殊寄存器中

mrs -->>将特殊寄存器中的数据写到普通寄存器中

注:特殊寄存器 cpsr 的读写访问只能使用 msr 和 mrs 指令

.text	/* 代码段 */
/* 将_start 声明为一个全局的函数, _start表示汇编程序的入口 */
.globl _start	/* globl 与 global 效果一样 */

_start:	/* 标签 : 类似于C语言的函数的名字, 表示函数的入口地址 */
    /*
	格式
		msr cpsr, 普通寄存器/立即数	@ cpsr = 普通寄存器/立即数
		mrs Rd, cpsr	@ Rd = cpsr
	*/

	@ 系统上电默认是svc 模式
	@ 修改系统模式到用户模式
	@ svc模式(10011) -->> 用户模式(10000)
	@ 1101 0011 -->> 1101 0000
	
	@ 1.通过 msr 直接修改
	@msr cpsr, #0xd0
	
	@ 2.通过位运算的方式
	mrs r0, cpsr
	bic r0, r0, #0x1f  @将[4:0]位清零
	orr r0, r0, #0x10
	msr cpsr, r0
		
	stop:
		b stop
.end

2.Load/Store内存读写指令

2.1单寄存器操作指令

ldr -->>将内存中的数据读到普通寄存器中,读4个字节的大小

str -->>将普通寄存器中的数据写到内存中,写4个字节的大小

ldrh -->>将内存中的数据读到普通寄存器中,读2个字节的大小

strh -->>将普通寄存器中的数据写到内存中,写2个字节的大小

ldrb -->>将内存中的数据读到普通寄存器中,读1个字节的大小

strb -->>将普通寄存器中的数据写到内存中,写1个字节的大小

.text	/* 代码段 */
/* 将_start 声明为一个全局的函数, _start表示汇编程序的入口 */
.globl _start	/* globl 与 global 效果一样 */

_start:	/* 标签 : 类似于C语言的函数的名字, 表示函数的入口地址 */
	/*
	其他用法:
	@ 将[Rm + offset]地址中的内容读到Rd寄存器中,Rm中的值不变
	ldr/ldrh/ldrb  Rd, [Rm, #offset]  
	@ 将[Rm]地址中的内容读到Rd寄存器中, 同时更新Rm中的地址:Rm=Rm+offset
	ldr/ldrh/ldrb  Rd, [Rm], #offset  
	@ 将[Rm + offset]地址中的内容读到Rd寄存器中,同时更新Rm中的地址:Rm=Rm+offset
	@ ! : 更新地址
	ldr/ldrh/ldrb  Rd, [Rm, #offset]!  
	
	@ 将Rn寄存器中的数据写到[Rm + offset]地址中,Rm中的值不变
	str/strh/strb  Rn, [Rm, #offset]
	@ 将Rn寄存器中的数据写到[Rm]地址中,同时更新Rm中的地址:Rm=Rm+offset
	str/strh/strb  Rn, [Rm], #offset
	@ 将Rn寄存器中的数据写到[Rm + offset]地址中,同时更新Rm中的地址:Rm=Rm+offset
	str/strh/strb  Rn, [Rm, #offset]!
	
offset : 偏移地址,偏移地址的大小是Load/Store指令可访问空间大小的整数倍。
	*/
	
	.if 0
		ldr r0, =0x12345678
		ldr r1, =0x40000800
		@ 将 r0 中的数据写到 [r1] 指向的地址空间
		str r0, [r1]
		@ 将 [r1] 指向的地址空间的数据读到r2寄存器中
		ldr r2, [r1]
	.endif
		ldr r0, =0x40000800
		ldr r1, =0x11111111
		ldr r2, =0x22222222
		ldr r3, =0x33333333
		@ 将r1中的数据写到[r0+4]地址中,r0中的值不变
		@ [0x40000804] = 0x11111111 , r0 = 0x40000800
		str r1, [r0, #4]
		
		@ 将r2中的数据写到[r0]地址中,同时更新r0中的地址,r0=r0+4
		@ [0x40000800] = 0x22222222 , r0 = 0x40000804
		str r2, [r0], #4
		
		@ 将r1中的数据写到[r0+4]地址中,同时更新r0中的地址,r0=r0+4
		@ [0x40000808] = 0x33333333 , r0 = 0x40000808
		str r3, [r0, #4]!
	
		
	stop:
		b stop
.end

执行结果:

ARM:特殊功能寄存器、Load/Store内存读写指令、栈操作指令_第1张图片

2.2多寄存器操作指令(ldm、stm)

.text	/* 代码段 */
/* 将_start 声明为一个全局的函数, _start表示汇编程序的入口 */
.globl _start	/* globl 与 global 效果一样 */

_start:	/* 标签 : 类似于C语言的函数的名字, 表示函数的入口地址 */
	/*
	ldm Rm, {寄存器列表}
		将Rm指向的连续的地址空间中的数据读到寄存器列表的每个寄存器中

	stm Rm, {寄存器列表}
		将寄存器列表中的每个寄存器中的数据写到Rm指向的连续的地址空间中
	
使用注意:
	1. Rm寄存器中的数据被当成一个地址看待
	2. 寄存器列表中的寄存器如果是连续的则使用"-"隔开;
	3. 寄存器列表中的寄存器如果不连续则使用","隔开;
	4. 寄存器列表中的寄存器要求从小到大依次书写,
		如果从大到小书写,要求依次用逗号隔开书写,但编译器会报警告。
	*/
	@ 不管寄存器列表中的寄存器的顺序如何书写,
	@ 永远都是小编号的寄存器对应低地址;
	@ 大编号的寄存器对应高地址
	
	ldr r0, =0x40000800
	ldr r1, =0x11111111
	ldr r2, =0x22222222
	ldr r3, =0x33333333
	ldr r4, =0x44444444
	@ 将r1-r4寄存器中的数据写到r0指向的连续的16字节空间中
	stm r0, {r1-r4}
	@ 将r0指向的连续的16字节空间的数据读到r5-r8中
	ldm r0, {r5-r7,r8}
		
	stop:
		b stop
.end

执行结果:

ARM:特殊功能寄存器、Load/Store内存读写指令、栈操作指令_第2张图片

 3.栈操作指令

1> 增栈: 压栈之后,栈指针向高地址方向移动。

2> 减栈: 压栈之后,栈指针向低地址方向移动。

3> 空栈: 当前栈指针指向的空间没有有效的数据,因此可以先压栈,压栈之后栈指针指向的空间就有有效的数据,因此需要移动栈指针,让栈指针指向一个没有有效数据的空间。

4> 满栈: 栈指针指向的空间有有效的数据,需要先移动栈指针,让栈指针指向一个空的位置,在进行压栈的操作,压制之后此时栈指针指向的空间又有有效的数据。

3.1栈的操作方式

栈的操作方式都是组合来使用的

满增栈 : Full Ascending -----> stmfa/ldmfs

满减栈 : Full Descending -----> stmfd/ldmfd

空增栈 : Empty Ascending -----> stmea/ldmea

空减栈 : Empty Descending -----> stmed/ldmed

ARM处理器默认采用的是满减栈,ARM指令集本身是支持以上4种栈的操作方式的所有的指令。

.text	/* 代码段 */
/* 将_start 声明为一个全局的函数, _start表示汇编程序的入口 */
.globl _start	/* globl 与 global 效果一样 */

_start:	/* 标签 : 类似于C语言的函数的名字, 表示函数的入口地址 */
	/*
	指令格式
	ldmfd sp!, {寄存器列表}
		将sp指向的栈空间中的数据读到寄存器列表的每个寄存器中

	stmfd sp!, {寄存器列表}
		将寄存器列表中的每个寄存器中的数据写到sp指向的栈空间中
	
使用注意:
	0. ! : 压栈和出栈之后都需要更新栈指针
	1. sp寄存器中的数据被当成一个栈空间的地址看待
	2. 寄存器列表中的寄存器如果是连续的则使用"-"隔开;
	3. 寄存器列表中的寄存器如果不连续则使用","隔开;
	4. 寄存器列表中的寄存器要求从小到大依次书写,
		如果从大到小书写,要求依次用逗号隔开书写,编译器会报警告。
	*/
	
	ldr sp, =0x40000800    @ 初始化sp的地址
	
	mov r0, #1
	mov r1, #2
	
	bl add_func1
	add r2, r0, r1
	nop
	b stop
	
	
	add_func1:
	stmfd sp!, {r0-r1, lr}
	mov r0, #3
	mov r1, #4
	bl add_func
	add	r3, r0, r1
	ldmfd sp!, {r0-r1, lr}	@ 也可以写成ldmfd sp!, {r0-r1, pc}
	mov pc, lr				
	
	
	add_func:
	stmfd sp!, {r0,r1}
	mov r0, #5
	mov r1, #6
	add r4, r0, r1
	ldmfd sp!, {r0,r1}
	mov pc, lr
		
	stop:
		b stop
.end

执行结果;

ARM:特殊功能寄存器、Load/Store内存读写指令、栈操作指令_第3张图片

 

你可能感兴趣的:(arm,嵌入式硬件)