多寄存器内存访问指令与栈

目录

一、多寄存器内存访问指令

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

 三、栈的种类与使用

3.1栈的概念

3.2栈的分类

四、栈的应用举例

        4.1叶子函数的调用过程举例

 4.2非叶子函数的调用过程举例


一、多寄存器内存访问指令


        @ 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}
        @ 先存储数据,后增长地址
        @ STMIB R11!,{R1-R4}
        @ 先增长地址,后存储数据
        @ STMDA R11!,{R1-R4}
        @ 先存储数据,后递减地址
        @ STMDB R11!,{R1-R4}
        @ 先递减地址,后存储数据
        

 

 
三、栈的种类与使用

3.1栈的概念

    栈的本质就是一段内存,程序运行时用于保存一些临时数据

    如局部变量、函数的参数、返回值、以及程序跳转时需要保护的寄存器等

3.2栈的分类

 

增栈:压栈时栈指针越来越大,出栈时栈指针越来越小

减栈:压栈时栈指针越来越大,出栈时栈指针越来越小

满栈:栈指针指向最后一次压入到栈中的数据,压栈时需要先移动栈指针到相邻位置然后再压栈

空栈:栈指针指向最后一次压入到栈中的数据的相邻位置,压栈时可直接压栈,之后需要将栈指针移动到相邻位置

栈分为空增(EA)、空减(ED)、满增(FA)、满减(FD)四种ARM处理器一般使用满减栈

 由于是满减栈使用STMDB进行压栈使用LDMIA进行出栈

        @ MOV R1, #1
        @ MOV R2, #2
        @ MOV R3, #3
        @ MOV R4, #4
        @ MOV R11,#0x40000020
        @ STMFD R11!,{R1-R4}
        @ LDMFD R11!,{R6-R9}
        

因为是FD可以直接用FD省的算怎么入怎么出,编译器会自动替换

  

四、栈的应用举例


        
4.1叶子函数的调用过程举例


得到了一个不应该的结果,由于主函数和子函数使用相同的寄存器,但用的值不同,在不增加寄存器的前提下让结果正确,就用到了栈。

        
        @ 初始化栈指针
        @ MOV SP, #0x40000020
@ MIAN:
        @ MOV R1, #3
        @ MOV R2, #5
        @ BL  FUNC
        @ ADD R3, R1, R2
        @ B STOP
        
@ FUNC:
        @ 压栈保护现场
        @ STMFD SP!, {R1,R2}
        @ MOV R1, #10
        @ MOV R2, #20
        @ SUB R3, R2, R1
        @ 出栈恢复现场
        @ LDMFD SP!, {R1,R2}
        @ MOV PC, LR
        

 
4.2非叶子函数的调用过程举例

        @ 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压栈保护

局部变量是栈中的,栈中数据不会自动清除所以,当分配一个新变量时,栈指针指到哪里变量的初始值就是该地址未清除时留下的值,而全局变量在BSS中,操作系统的初始化时会将这里自动清零,所以全局变量的初值是0.
        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇努力学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值