ARM 寻址举例(19)

举例: 计算一个数组的所有元素的和。

复制代码
	area first, code, readonly                                
	code32
	entry
start
	ldr r0,=array
;	adr r0,array   ;ADR为小范围的地址读取伪指令
loop
	ldr r1,[r0],#4
	cmp r1,#0
	addne r4,r4,r1
	bne loop
stop
	b stop
	; DCD 伪操作  数据缓冲池技术   
	; dcd  机器码
array
	dcd 0x11
	dcd 0x22
	dcd 0

首先是关于 dcd 指令的解释, dcd是一个 伪指令, 表示 在内存中分配一篇连续的单元,并且复制。

ldr r0, =array , 代表的是 加载 array 的地址 到r0 寄存器。相当于 C语言的 & 符号。

ldr r1, r0, #4, 表示,将r0 的内容放到r1 , 并且r0 加4,

然后比较r1 是不是等于0 , 如果等于0 就代表已经到数组的最后了,就进入死循环,

如果不是0 , 那么就把 和 放到r4 的寄存器中。

然后是第二个例子: 内存的压栈与出栈。

复制代码
    area first, code, readonly                               
	code32
	entry
Start
   ;mov r0, #0x40000000
	ldr sp, =0x40001000  ;注意地址

	mov r1, #0x11
	mov r2, #0x22
	mov r3, #0x33
	mov r5, #0x55
	; 压栈
	stmfd sp!, {r1-r3, r5}
	;stmia r0!, {r1-r3, r5} ; 加感叹号是自动修改基地址
    mov r1, #0 
	mov r2, #0
	mov r3, #0
	mov r5, #0

	ldmfd sp!, {r1-r3, r5}
	;ldmdb r0!, {r2,r1,r3, r5} ; 寄存列表书写顺序无所谓, 低地址内容对应低编号寄存器 
stop 
	b stop 
	end

这里需要 说明的是 两个指令

STMFD 指的就是 进行压栈, LDMFD指的就是出栈。

ldr sp, =0x40001000 , 值得是在 设置栈指针。

stmfd sp!, {r1,-r3,r5}, 这里代表的是,将寄存器组的数据,压栈到 sp 指针指向的地方,并且, sp 指针,需要同步向下走。

注意: r1,r2,r3,r5 ,在往内存中压栈的时候, 顺序是这样的, 内存中的低地址,存放的是 低标号的寄存器的值。

ldmfd sp! ,{r1-r3,r5} , 代表的是,出栈的操作, 出栈的顺序也是, 低地址的内存的值,对应的是低标号的寄存器。

这样的话,就可以完美的回复到之前压栈的寄存器中。

在然后的例子就是函数的嵌套调用。

复制代码
 	area first, code, readonly                   
	code32
	entry
start
	ldr sp, =0x40002000
	mov r1, #0x11
	mov r2, #0x22
	mov r3, #0x33
	mov r5, #0x55
	bl child_func1        ; 【先写跳转到 child_func1,再写跳转到child_func】	
	add  r0, r1,r2
stop 
	b stop 
; 非叶子函数	
child_func
	stmfd sp!, {r1-r3,r5,lr} ;;;在子函数里首先将所有寄存器值压栈保存,
	                   ;;防止在子函数里篡改原本在主函数里运算需要的值,
	                   ;;通常需要把r0-r12全都保存,为了安全和程序通用性应该这么做
	mov r1, #10       ;;在这里子函数想怎么做自己的事情就可以做自己的事情
    bl child_func1
	ldmfd sp!, {r1-r3,r5,lr};;;;; 放在主函数bl之后的第一句行吗?
	mov pc, lr
child_func1
 	stmfd sp!, {r1-r3,r5};;;不论嵌套多少层子函数,都是先压栈,
  	mov r1, #11
	ldmfd sp!, {r1-r3,r5};;对应的,在返回到自己的父函数之前将自己出栈
	mov pc, lr
	end

ldr sp, =0x40002000 ,这是在设置栈指针。

bl child_func1 这是在进行跳转,这里有个隐含的操作,cpu 会自动的把下一条 PC指针的值, 放到LR寄存器中。

stmfd sp! , {r1-r3,r5,lr} , 这是在压栈, 这里特别提到了,lr ,这是把函数返回的PC值, 也压栈了。

bl child_func1 , 与之前的操作是一样的。

然后就是 返回的操作了。

ldmfd sp!, {r1-r3,r5} 这是在进行出栈了。

mov pc, lr ,这个指令就是在返回了。

相关推荐
A小辣椒1 天前
TShark:Wireshark CLI 功能
linux
A小辣椒1 天前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言