ARM的读写内存指令与栈的应用
1.基础读写指令
写内存指令:STR
@ MOV R1, #0xFF000000@ MOV R2, #0x40000000@ STR R1, [R2] @ 将R1寄存器中的数据写入到R2指向的内存空间
需注意,此命令是将R1中的数据写给R2所指向的内存空间,而不是直接把R1的数据赋给R2,R2寄存器中存放的是数据要被写入的内存的起始地址,由于使用的是STR指令,所以R2中存放的地址时不会改变的,如果后续再次向R2所指向的内存中写数据,则原来的数据会被覆盖。
读内存指令:LDR
@ MOV R1, #0xFF000000@ MOV R2, #0x40000000@ LDR R3, [R2]@ 将R2指向的内存空间中的数据读取到R3寄存器
原理基本同上,是将R2存放的地址指向的空间中的数据读取到R3寄存器中
读写指定的数据类型:
在ARM中有三种数据类型,Byte类型占一个字节,Halfword类型占两个字节,Word类型占四个字节,如果我们指向读取某个数据类型的数据,只需要在读写指令后加上后缀即可,示例如下:
@ MOV R1, #0xFFFFFFFF@ MOV R2, #0x40000000@Byte类型:@ STRB R1, [R2]@ 因为Byte类型占一个字节也就是8bit,@所以指令的含义是将R1寄存器中的数据的前8位写入到R2指向的内存空间@Halfword类型:@ STRH R1, [R2] @ 将R1寄存器中的数据的前16位写入到R2指向的内存空间@Word类型:@ STR R1, [R2] @ 将R1寄存器中的数据的前32位写入到R2指向的内存空间@ LDR指令同样支持以上后缀,并且含义相同
2.基址加变址寻址:
前索引和后索引:
由其定义可知,我们要操作的地址变成了 基本地址 + 可变地址,如下程序所示,要进行读写操作的内存的地址变成了中括号中的数据的和。
@ MOV R1, #0xFFFFFFFF@ MOV R2, #0x40000000@ MOV R3, #4@ STR R1, [R2,R3]@ 将R1寄存器中的数据写入到R2+R3指向的内存空间,也就是0x40000004指向的地址空间@ STR R1, [R2,R3,LSL #1]@ 将R1寄存器中的数据写入到R2+(R3<<1)指向的内存空间
上面代码中将可变地址R3写入中括号里的方法叫做基址加变址寻址的前索引方式,而将其写在中括号后为后索引方式,他们俩的含义如下:
@ 前索引@ MOV R1, #0xFFFFFFFF@ MOV R2, #0x40000000@ STR R1, [R2,#8]@ 将R1寄存器中的数据写入到R2+8指向的内存空间@ 后索引@ MOV R1, #0xFFFFFFFF@ MOV R2, #0x40000000@ STR R1, [R2],#8@ 将R1寄存器中的数据写入到R2指向的内存空间,然后R2自增8
自动索引:
除了他们俩之外,还有一种索引叫做自动索引,其定义如下:
@ MOV R1, #0xFFFFFFFF@ MOV R2, #0x40000000@ STR R1, [R2,#8]!@ 将R1寄存器中的数据写入到R2+8指向的内存空间,然后R2自增8
需注意,自动索引! 的位置是不能改变的并且 必须要是英文的
3.多寄存器内存访问指令:
多寄存器内存访问指令,其含义就是同时读写多个寄存器中的数据,示例如下:
@ 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寄存器中
与单独读写一个寄存器的数据相比,指令由STR和LDR变成了STM和LDM,其存放 要进行读或写操作的地址 的寄存器变成了目标寄存器,也就是作为了指令后的第一个参数,要被读入或写的数据所要存放的寄存器被放在一个大括号中,ARM会依次将其读取或写入到相应的位置,大括号中的写法也可以使用逗号隔开,例如{R1,R2,R3,R4},但是无论其顺序怎么改变,他在进行操作时都是低地址对应小号的寄存器,例如上边程序的写指令即使写成 STM R11,{R2,R1,R4,R3} 他在写入到R11为起始地址的内存空间中时也是先将R1存放到底地址0x4000020当中,读指令也是如此。
自动索引也同样适用于多寄存器内存访问指令,只是感叹号位置发生了改变,具体如下:
@ STM R11!,{R1-R4}
执行完这条指令后,R1-R4会被依次写入在R11指向的地址处,因为写入了四个数据,所以R11所储存的地址会自增16个字节。
多寄存器内存访问指令的寻址方式:
STM指令与LDM指令有四个后缀,分别为IA,IB,DA,DB,下面的这些都是在其有自动索引时的解释,其意义分别为:
- STMIA R11! :先储存数据,然后地址在增加
- STMIB R11! : 地址先增加,然后再储存数据
- STMDA R11! :先储存数据,然后地址递减
- STMDB R11! :地址先减少,然后再储存数据
如下图所示,我用大白话形容一下,IA就是先把你要写入的第一条数据先写进R11存放的地址中,然后再将R11的地址增加去存放下一个数据,直到数据全部存完后R11的地址在增加一次指向写入的最后一个数据的下一个地址,IB就是先让R11的地址增加一次,然后再开始写入数据,最后R11的地址会指向所写入的最后一条数据。DA和DB只是存储方向相反而已,方式是相同的,注意写入数据和增加地址的过程是一一对应的,写一条就要加一次,数据是一条一条存放到内存中而不是一下全放进去然后地址一次性增加。
@ 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}@ 先递减地址,后存储数据
ARM使用的大多是
4.ARM栈的种类与使用:
概念:栈的本质就是一段内存,程序运行时用于保存一些临时数据,如局部变量、函数的参数、返回值、以及程序跳转时需要保护的寄存器等
栈的分类:
- 增栈:压栈时栈指针越来越大,出栈时栈指针越来越小
- 减栈:压栈时栈指针越来越大,出栈时栈指针越来越小
- 满栈:栈指针指向最后一次压入到栈中的数据,压栈时需要先移动栈指针到相邻位置然后再压栈
- 空栈:栈指针指向最后一次压入到栈中的数据的相邻位置,压栈时可直接压栈,之后需要将栈指针移动到相邻位置
增减和空满是组合在一起的,栈分为空增(EA)、空减(ED)、满增(FA)、满减(FD)四种,EA对应上面的IA,ED对应DA,FA对应IB,FD对应DB可以对应ARM处理器一般使用满减栈,所以对ARM的栈做存储操作时可以直接使用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.叶子函数的调用过程举例@ 初始化栈指针@ 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@ 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压栈保护
相关文章:

ARM的读写内存指令与栈的应用
1.基础读写指令 写内存指令:STR MOV R1, #0xFF000000 MOV R2, #0x40000000 STR R1, [R2] 将R1寄存器中的数据写入到R2指向的内存空间 需注意,此命令是将R1中的数据写给R2所指向的内存空间,而不是直接把R1的数据赋给R2,R2寄存器…...

2022年平均工资出炉,IT行业又是第一
根据5月9日国家统计局最新资料显示,2022年,全国城镇非私营单位就业人员年平均工资为114029元,比上年增长6.7%,扣除通胀后实际增长4.6%。其中,行业间的差距相当明显。根据资料显示,2022年无论是在私营单位还…...

ov2640子设备核心操作详细分析
ov2640子设备核心操作详细分析 文章目录 ov2640子设备核心操作详细分析ov2640_subdev_core_ops核心操作获取寄存器值ov2640_g_register设置寄存器值ov2640_s_registeri2c_smbus_xferi2c_imx_xferi2c_smbus_xfer_emulatedi2c_transfer__i2c_transfer 设置ov2640的电源ov2640_s_p…...
MATLAB语句实现方阵性质的验证
系列文章目录 MATLAB绘图函数的相关介绍——海底测量、二维与三维图形绘制 MATLAB求函数极限的简单介绍 matlab系统环境思维导图 文章目录 系列文章目录 1. MATLAB语句验证方阵的六个性质如下 2. 六个性质的解释如下 3. 使用随机矩阵进行验证的代码示例如下 总结 前言 …...
使用Springboot AOP进行请求接口异常监控
常用注解 Aspect 切面类 Before 前置 AfterReturning 后置 Around 环绕 AfterThrowing 异常 切入点设置 execution(public * *(..)) 定义任意公共方法的执行 execution(* set*(..)) 定义任何一个以"set"开始的方法的执行 execution(* com.sys.service.UserService…...

【云原生|Kubernetes】05-Pod的存储卷(Volume)
【云原生Kubernetes】05-Pod的存储卷(Volume) 文章目录 【云原生Kubernetes】05-Pod的存储卷(Volume)简介Volume类型解析emptyDirHostPathgcePersistentDiskNFSiscsiglusterfsceph其他volume 简介 Volume 是Pod 中能够被多个容器访问的共享目录。 Kubern…...
Python实现数据结构
文章目录 一、Python实现数据结构1.1 python实现单向链表1.2 python实现单向循环链表1.3 python实现双向链表 一、Python实现数据结构 1.1 python实现单向链表 singleLinkedList.py class SingleNode:"""the node of single link list"""def …...

esp32CAM环境安装教程---串口驱动安装
前言 (1)本人安装好arduino 的ESP32环境之后, 发现一直下载不进去程序。一直说Cannot configure port, something went wrong. Original message: PermissionError。 (2)查阅了很多资料,用了各种办法&#…...
Java中List和Array转换
文章目录 List -> Array1. 调用toArray()方法直接返回一个Object[]数组:2. 给toArray(T[])传入一个类型相同的Array,List内部自动把元素复制到传入的Array中:3. 通过List接口定义的T[] toArray(IntFunction<T[]> generator)方法&…...
如何能确定数据库中root用户的密码是什么
如果您无法确定数据库中 root 用户的密码,有几种方法可以尝试找回或重置密码: 1. 使用已知密码:如果您有之前设置的 root 用户密码,可以使用该密码进行登录。 2. 查找密码文件:在某些情况下,MariaDB 可能…...

由浅入深Netty协议设计与解析
目录 1 为什么需要协议?2 redis 协议举例3 http 协议举例4 自定义协议要素4.1 编解码器4.2 什么时候可以加 Sharable 1 为什么需要协议? TCP/IP 中消息传输基于流的方式,没有边界。 协议的目的就是划定消息的边界,制定通信双方要…...
iptables防火墙(1)
iptables防火墙 一、iptables概述二、netfilter/iptables 关系三、四表五链1.四表2.五链 四、规则链之间的匹配顺序五、规则链内的匹配顺序六、iptables安装与配置七、常用的控制类型八、常用的管理选项九、规则命令1.添加新规则2.查看规则列表3.设置默认策略4.删除规则5.清空规…...
第九章 Productions最佳实践 - Productions开发的最佳实践
文章目录 第九章 Productions最佳实践 - Productions开发的最佳实践Productions开发的最佳实践项目目标项目交付文档 第九章 Productions最佳实践 - Productions开发的最佳实践 Productions开发的最佳实践 本章是一个总体概述,旨在帮助团队成员为从事生产项目做好…...
RocketMQ 怎么实现的消息负载均衡以及怎么能够保证消息被顺序消费
一、RocketMQ 怎么实现的消息负载均衡 RocketMQ是一种开源的分布式消息中间件,它使用了一种称为消息负载均衡的机制来实现消息的分发和消费的负载均衡。RocketMQ的消息负载均衡主要是通过以下两个方面实现的: 消息队列分组(Message Queue G…...

【随笔记】全志 T507 PF4 引脚无法被正常设置为中断模式的问题分析
相关信息 硬件平台:全志T507 系统版本:Android 10 / Linux 4.9.170 问题描述:PF4 无法通过标准接口设置为中断模式,而 PF1、PF2、PF3、PF5 正常可用。 分析过程 一开始以为是引脚被其它驱动占用引起,或者该引脚不具…...

人手一个 Midjourney,StableStudio 重磅开源!
人手一个 Midjourney,StableStudio 重磅开源! Stability AI 公司在上个月 19 号推出了 Alpha 版本 StableLM 大语言模型,包含了 30 亿和 70 亿参数,并且支持商用。如今他们再次推出了 AI 图像生成平台 StableStudio,这…...

iptables防火墙(2)
iptables防火墙(2) 一、SNATSNAT应用环境SNAT原理SNAT转换前条件扩展 二、DNATDNAT应用环境DNAT原理DNAT转换前提条件扩展 三、防火墙规则的备份和还原导出(备份)所有表的规则导入(还原)规则 一、SNAT SNA…...

Windows和Kali上使用proxychains代理流量
Windows和Kali上使用proxychains代理流量 PS. 本文演示都是在kali进行的,如有出入还请联系我哦1. Linux(Debian)1.1. 检查一下是否有proxychains1.2 修改config文件 2. Linux(Debian)安装proxychians43. Windows3.1 下载3.2 配置 4. Windows下的配置5. 测试 PS. 写这…...

KEYSIGHT MSOS204A 2GHZ 4通道DSOS204A高清晰度示波器
KEYSIGHT是德DSOS204A/MSOS204A高清晰度示波器 附加功能: 2 GHz 带宽(可升级) 4 个模拟通道和 16 个数字通道 最大存储深度:800 Mpts(2 通道),400 Mpts(4 通道) 最大…...

最新Java适配商城系统
城前端功能展示 商城移动端 后端基于SpringBoot 研发,前端使用 Vue、uniapp开发 前后端分离,支持分布式部署,支持Docker,各个API独立,并且有独立的消费者 api不需要单独部署,只需启动一个jar包就可以正…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...