8.栈的种类与应用

本文详细介绍了ARM处理器中的多寄存器内存访问指令,包括STMR和LDMR指令,以及它们的不同寻址方式如增加和减少地址。同时,阐述了栈的概念、分类和使用,特别是满减栈在ARM中的应用,并通过实例展示了函数调用过程中的栈操作。此外,解释了C语言中未初始化局部变量为何可能含有随机数的原因,因为它们在栈上分配且可能保留前一次使用栈的数据。
摘要由CSDN通过智能技术生成

多寄存器内存访问指令

@ 多寄存器内存访问指令:可以将多个寄存器写入内存,或从内存中读取多个寄存器
		@ MOV R1, #1
		@ MOV R2, #2
		@ MOV R3, #3
		@ MOV R4, #4
		@ MOV R11,#0x40000020
		@ STM R11,{R1-R4}
		@ 将R1-R4寄存器中的数据写入到以R11为起始地址的内存空间中
		@ LDM R11,{R6-R9}
		@ 将以R11为起始地址的内存空间中的数据读取到R6-R9寄存器中
		
		@ 当寄存器编号不连续时,使用逗号分隔
		@ STM R11,{R1,R2,R4}
		@ 不管寄存器列表中的顺序如何,存取时永远是低地址对应小编号的寄存器
		@ STM R11,{R3,R1,R4,R2}
		@ 自动索引照样适用于多寄存器内存访问指令
		@ STM R11!,{R1-R4}

多寄存器内存访问指令的寻址方式

在这里插入图片描述

@ 多寄存器内存访问指令的寻址方式
		@ MOV R1, #1
		@ MOV R2, #2
		@ MOV R3, #3
		@ MOV R4, #4
		@ MOV R11,#0x40000020
		@ STMIA R11!,{R1-R4}
		@ 先存储数据,后增长地址,Increase after
		@ STMIB R11!,{R1-R4}
		@ 先增长地址,后存储数据,Increase before
		@ STMDA R11!,{R1-R4}
		@ 先存储数据,后递减地址,Decrease after
		@ STMDB R11!,{R1-R4}
		@ 先递减地址,后存储数据,Decrease before

栈的种类与使用

栈的概念

在这里插入图片描述
压栈:往内存存数据
出栈:往内存取数据

栈的分类

增栈:往SP寄存器指向的地址存数据,依次往高地址存
减栈:往SP寄存器指向的地址存数据,依次往低地址存

增栈减栈都是压栈。

取数据时按照数据结构中栈的结构,先进后出。

满栈:栈指针指向的地址中存了数据,当有新数据来临,栈指针要向空地址移动一格再存新数据。
空栈:栈指针指向的地址中没有存数据,当心数据来临,栈指针不用移动可以直接存新数据。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
ARM处理器使用满减栈:对应的指令是STMDB,读内存的指令用LDMIA。

这么做就是要我们自己算压栈和出栈用哪个后缀

@ 栈的种类与使用
		@ MOV R1, #1
		@ MOV R2, #2
		@ MOV R3, #3
		@ MOV R4, #4
		@ MOV R11,#0x40000020
		@ STMDB R11!,{R1-R4}
		@ LDMIA R11!,{R6-R9}

采用EA、ED、FA、FD四个后缀可以直接让处理器自己选择对应的进出栈方式

@ 栈的种类与使用
		@ MOV R1, #1
		@ MOV R2, #2
		@ MOV R3, #3
		@ MOV R4, #4
		@ MOV R11,#0x40000020
		@ STMFD R11!,{R1-R4}
		@ LDMFD R11!,{R6-R9}

栈的应用举例

@ 栈的应用举例
		
		@ 1.叶子函数的调用过程举例:main调了FUNC,FUNC没有调其它函数,FUNC就像叶子一样成了main这个树根的最后的函数
		
		@ 初始化栈指针
		@ MOV SP, #0x40000020
@ MIAN:
		@ MOV R1, #3
		@ MOV R2, #5
		@ BL  FUNC
		@ ADD R3, R1, R2	为了避免R1、R2的值不被FUNC函数破坏
		@ B STOP
		
@ FUNC:
		@ 压栈保护现场
		@ STMFD SP!, {R1,R2}	将R1、R2的值存到栈中
		@ MOV R1, #10
		@ MOV R2, #20
		@ SUB R3, R2, R1
		@ 出栈恢复现场
		@ LDMFD SP!, {R1,R2}	再将R1、R2的值从栈中取出
		@ MOV PC, LR
		
		@ 2.非叶子函数的调用过程举例:main调了FUNC1,FUNC1调用了FUNC2,FUNC1是非叶子函数,要将LR压栈

		@ MOV SP, #0x40000020
@ MIAN:
		@ MOV R1, #3
		@ MOV R2, #5
		@ BL  FUNC1
		@ ADD R3, R1, R2
		@ B STOP		
@ FUNC1:
		@ STMFD SP!, {R1,R2,LR}
		@ MOV R1, #10
		@ MOV R2, #20
		@ BL  FUNC2
		@ SUB R3, R2, R1
		@ LDMFD SP!, {R1,R2,LR}
		@ MOV PC, LR
@ FUNC2:
		@ STMFD SP!, {R1,R2}
		@ MOV R1, #7
		@ MOV R2, #8
		@ MUL R3, R1, R2
		@ LDMFD SP!, {R1,R2}
		@ MOV PC, LR
		
		@ 执行叶子函数时不需要对LR压栈保护,执行非叶子函数时需要对LR压栈保护

为什么C语言中不初始化局部变量其值是随机数

由于局部变量存在栈里,而栈在之前使用过后不会被清空,而初始化一个局部变量后其地址是栈指针指向的地址,即栈指针上次使用栈的地址,因此如果不给局部变量赋初值,其值会是上次使用栈存的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值