ARM映像文件组成
引言
ARM编译器将各种源文件(汇编文件、C语言程序文件、C++语言程序文件)编译生成ELF格式的目标文件(后缀为.o文件,以下将目标文件简称为.o文件),.o文件经过连接器,和C/C++运行时库一起编译生成ELF格式的映像文件(image,如常用的MKD使用 fromelf.exe生成的bin文件就是image),bin文件可以直接写入到flash中,实际上使用jlink下载的内容就是bin文件的内容(hex文件是包含地址信息的bin文件,可以理解为hex=地址信息+bin)。下文中也将映像文件称为bin文件或者image文件。编译流程如下图。

图片来源于《Introductiontothe Armv8-M Architecture and its ProgrammersModel》
相关文档在后面有链接
1、ARM映像文件的组成
1.1 ARM映像文件的组成
ARM映像文件是一个层次性的结构,有如下三部分组成:域(region)、输出段(output section)、输入段(input section),三者有如下的关系:
-
一个bin文件由一个或多个域组成
-
一个域包含一个或多个输出段
-
一个输出段包含一个或多个输入段
-
各输入段包含了目标文件中的代码和数据

输入段可以理解为我们写的代码具体包含哪些属性。输入段包含4类:代码、已经初始化的数据、未初始化的存储区域、内容初始化为0的区域,即(code+RW)、ZI、ZI,分别为RO段、RW段、ZI段。编译器根据输入段的属性,将这些输入段分组,组成不同的输出段以及域。
一个输出段里面包含了一些列具有相同RO、RW、ZI属性的输入段。输出段的属性于其中包含的输入段的属性相同,在一个输出段内部,各个输入段是按照一定的规律排序的。
一个域包含1到3个输出段,其中各输出段的属性各不相同。各输出段的排列顺序是由其属性决定的,RO属性排在最前面,其次RW,最后ZI段。一个域通常映射到一个物理储存器上,如flash、ram等。
抛开上面较书面的表达,我们已keil为例。在mdk中,域的定义由分散链接文件(sct)决定,随便打开一个keil的sct文件,可以看到:

在sct中,定义了三个域,名字分别为LR_IROM1、ER_IROM1、RW_IRAM1,LR_IROM1是最终的bin文件,ER_IROM1是加载域,RW_IRAM1是执行域。keil生成的bin中,一般包含三个段:RO段(代码+只读数据)、RW段、ZI段。一个域至少包含上述三个段中的一个。
对于一个C文件来说,可能包含代码、全局变量、只读数据、为0的数据、未初始化的数据。在编译的时候,会自动将各个段进行分类,例如led.c文件,会将代码部分放到RO段里面,全局变量放到RW段,未初始化的变量存放到ZI段。
以下进行一些猜测:如果说我们有led1.c和led2.c两个文件,二者分别生成RO、RW、ZI,则可以理解为:led1.c和led2.c是输入段1.1.1和1.1.2,他们生成的RO、RW、ZI为输出段1.1和1.2,最终合并在域1中(实际上我们知道,这个域存放的地方是M4芯片内部的flash)。
1.2 ARM映像文件各组成部分的地址映射
bin文件在储存系统(如内部flash)中的地址有两种:一种是bin文件位于储存器中时的地址,称为加载地址。一种时bin文件运行时的地址,称为运行地址。之所以分成两类,是因为在bin文件中,有些域是可以移动到新的储存区域,比如RW域中的数据在运行的时候会搬运到RAM中。
如下图所示为例,flash的起始地址为0x0800 0000,依次存放RO、RW、ZI段,在运行的时候,ZI和RW会搬运到SRAM中。

一个bin文件一般包含若干个域,一个域包含若干个输出段。ARM链接器在链接时需要知道如下信息才能正确的生成bin文件:
-
分组信息 决定如何将各输入段组织成相应的输出段和域
-
定位信息 决定各域在储存空间中的起始地址
根据bin文件中地址映射的复杂程度,可以使用命令行选项的方式提供或者提供配置文件(如keil的sct文件)
2、ARM映像文件的入口点
2.1 ARM映像文件中的两类入口点
bin文件有两类入口点:一种是映像文件运行时的入口点,称为初始入口点(initial entry point),另一种时普通的入口点(entry point)。
初始入口点时bin文件运行时的入口点,每个bin只有唯一的初始入口点,保存在ELF头文件中。如果bin是被操作系统加载的,则OS正是用过跳转到该初始入口点处执行来加载该映像文件。
普通入口点是在汇编中用ENTRY来定义的,在嵌入式系统中一个典型的用途就是将中断服务程序定义为普通入口点,防止在链接的时候将中断服务程序给删除了。在C库中,__main是入口点。在sct中,可以看到:
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x10000000 0x0000F000 { ; load region size_regionER_IROM1 0x10000000 0x0000F000 { ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO)}RW_IRAM1 0x1FFFC000 0x00003000 { ; RW data.ANY (+RW +ZI)}
}
其中REST就是初始入口点属性,将初始入口点放到ROM中,在start.s中可以看到如下的汇编写法:

这个就是初始入口点定义的代码部分。
在一个bin文件中,只有一个初始入口点,普通入口点可以由多个,初始入口点可以是普通入口点,也可以不是。
2.2 定义初始入口点
初始入口点需要满足如下两个条件:
-
初始入口点必须位于bin文件的运行时域内
-
包含初始入口点的运行时域不能被覆盖,它的加载地址和运行地址必须相同(这种域称为固定域,root region)
可以使用链接选项-entry address来指定bin的初始入口点,address表示初始入口点的地址。
如果bin被一个加载器加载再运行,如被引导程序或者OS加载,则bin文件必须包含一个初始入口点。比如,一个操作系统的映像文件被一个引导程序加载,这时程序跳转到该映像文件的初始入口点处开始执行,它覆盖了引导程序,称为系统中的操作系统。这种映像文件中通常包含了其它的普通入口点,这些入口点一般为异常中断处理程序的入口地址。
当用户没有指定链接选项-entry指定链接地址,则按照如下规则决定映像文件的初始入口点:
-
如果输入的目标文件中只有一个普通入口点,该普通入口点被链接器当作bin文件的初始入口点
-
如果输入的目标文件没有普通入口点或者普通入口点多余一个,则链接器生成的bin文件不包含初始入口点,且产生警告。
2.3 普通入口点的用法
普通入口点一般用作两种用途:
-
指定中断服务程序的入口,防止链接的时候删除中断服务器程序代码
-
没有指定链接选项-entry address且输入的目标文件中只有一个普通入口点,则该普通入口点被当作初始入口点
3、输入段的排列顺序
链接器根据各输入段的属性来组织这些输入段,具有相同属性的输入段被放到域中一段连续的地址空间中,组成一个输出段。在输出段中,各输入段的起始地址与输出段的起始地址和该输出段中各输入段的排列顺序有关。
通常情况下,输出段中各输入段的排列顺序由如下几个因素决定:
-
输入段的属性
-
输入段的名称
-
各输入段在连接命令行的输入段列表中的排列顺序
按照输入段的属性,排列顺序如下:
-
只读的代码段(RO-code)
-
只读的数据段(RO-data)
-
可读写的代码段(RW-code)
-
其它以及初始化的数据段(RW-data)
-
未初始化的数据(ZI)
对于相同属性的输入段,按照名称顺序来排序,输入段的名称区分大小写,按照ASCII码顺序进行排序。如果输入段的名称也相同,按照其在输入段列表中的顺序进行排序。也就是说,即使各输入段的属性和名称保持不变,若在编译时,各个输入段在列表中的排列属性不同,生成的映像文件也将不同。
可以使用连接选项-first、-last改变输入段的排列顺序,也可以使用配置文件改变输入段的排列顺序。排序规则影响因素有三个:输入段属性、输入段名称、输入段在列表中的顺序。连接选项-first、-last只对输入段的名称和在列表中的顺序有效,无法改变因输入段的属性进行的排序规则。
在各个输入端排好序之后,在最终确定各个输入段的起始地址之前,可以通过填充“补丁”使各个输入段满足地址对齐要求。
4、题外话
本篇文章是博主在学习ARM体系的时候写的笔记性质的文章,先在CSDN上分享,用到的参考文档有:
- 《Introductiontothe Armv8-M Architecture and its ProgrammersModel》
- 《ARM体系结构与编程》
相关文档已经上传到博主的仓库里面,链接:https://gitee.com/zichuanning520/htq_library
相关文章:
ARM映像文件组成
引言 ARM编译器将各种源文件(汇编文件、C语言程序文件、C语言程序文件)编译生成ELF格式的目标文件(后缀为.o文件,以下将目标文件简称为.o文件),.o文件经过连接器,和C/C运行时库一起编译生成ELF格…...
redis怎么设计一个高性能hash表
问题 redis 怎么解决的hash冲突问题 ?redis 对于扩容rehash有什么优秀的设计? hash 目标是解决hash冲突,那什么是hash冲突呢? 实际上,一个最简单的 Hash 表就是一个数组,数组里的每个元素是一个哈希桶&…...
《软件方法》强化自测题-总纲(6)
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 按照业务建模、需求、分析、设计工作流考察,答案不直接给出,可访问自测链接或扫二维码自测,做到全对才能知道答案。 知识点见《软件方法》&#x…...
vue2中,下拉框多选和全选的实现
vue2中,下拉框多选和全选的实现 代码布局在methods: 中添加功能函数较为完整的一个整体代码: 如图所示点击全选即可完成下拉框中全部子项的全部的选中,同时取消全选即可全部取消选择。 代码布局 <div class"chos-box2"><…...
Android-Framework 默认音乐音量最大
代码位置:frameworks/base/services/core/java/com/android/server/audio/AudioService.java -712,6 712,9 public class AudioService extends IAudioService.Stub}} // force music max volume AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] MA…...
formData对象打印不出来
用el-upload上传图片 以流的形式传给后台 所以用formData对象带数据 let formData new FormData() formData.append(name,monkey7) console.log(formData) 明明已经把数据append进去了 console.log在控制台却打印不出 后来发现他得用formData.get("xxx"…...
【Web安全】SQL注入攻击几种常见防御手法总结
文章目录 前言一、使用参数化查询二、输入验证和过滤三、使用存储过程四、最小权限原则五、使用ORM框架六、使用准备语句七、使用安全的数据库连接八、避免动态拼接SQL语句九、使用防火墙和入侵检测系统(一)防火墙(二)入侵检测系统(Intrusion Detection System,简称IDS)十、定期…...
Linux网络编程杂谈(聊聊网络编程背后的故事)
数据是如何传输到物理网络上的? 以TCP为例,当 TCP 决定发送数据时,这些数据需要经过多个处理阶段才能真正被传输到物理网络。其中一个关键步骤是将数据移动到网络接口卡 (NIC)。以下是这个过程的详细描述: 数据序列化: TCP 会为要…...
执行Maven项目时,无法解析项目的依赖关系
报错[ERROR] Failed to execute goal on project pdms-services: Could not resolve dependencies for project ..... 在IDEA ----> setting ---->Remote Jar Repositories ----> Maven jar repositories中添加远程仓库的http地址。 再次进行maven的clean和install就好…...
索引有哪些缺点以及具体有哪些索引类型
索引的优缺点 优点: 合理的增加索引,可以提高数据查询的效率,减少查询时间 有一些特殊的索引,可以保证数据的完整性,比如唯一索引 缺点: 创建索引和维护索引需要消耗时间 索引需要额外占用物理空间 对创建…...
前端学成在线项目详细解析二
12-banner区域-课程表布局 HTML布局 <div class"right"><h3>我的课程表</h3><div class"content">1</div> </div> CSS样式 /* 课程表 */ .banner .right {margin-top: 60px;width: 218px;height: 305px;background-…...
Linux 网卡性能优化设置
在高速网络传输中,每秒传输的数据量非常大。网络设备设置有一种缓存机制,即“缓存区”,在 Linux 系统中,网卡缓冲分为两种类型:软件缓冲区和硬件缓冲区。 要提高网络吞吐率,首先当然是升级linux kernel。其…...
华为OD 最大嵌套括号深度(100分)【java】B卷
华为OD统一考试A卷+B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入: 我用夸克网盘分享了「华为O…...
“微信小程序登录与用户信息获取详解“
目录 引言微信小程序微信登录介绍1. 微信登录的基本概念2. 微信小程序中的微信登录 微信小程序登录的wxLogin与getUserProfile的区别1. wx.login()2. wx.getUserProfile()3.两者区别 微信小程序登录的理论概念1. 微信登录流程2. 用户授权与登录态维护 微信小程序登录的代码演示…...
软考-防火墙技术与原理
本文为作者学习文章,按作者习惯写成,如有错误或需要追加内容请留言(不喜勿喷) 本文为追加文章,后期慢慢追加 by 2023年10月 防火墙概念 根据网络的安全信任程度和需要保护的对象,人为地划分若干安全区域…...
MOS管型号
MOS 管型号 N型 型号类型电压电流Rds封装资料AP60N03DFN30V60A45mΩPDFN3x3-8L手册 P型 型号类型电压电流Rds封装资料AO4447AP30V-18.5A8.2mΩSOIC-8手册 NP型 型号类型电压电流Rds封装资料NP4606PN30V7A、-6A45mΩSOP8手册KS3640MBPN30V20A、-22A45mΩPDFN3333手册NCE30…...
龙测票选,5本最受欢迎的软件测试书籍
随着技术的发展,软件测试所涉猎的领域越来越广泛,包括测试理论、方法、管理、工具等,一直在随之变化。对新手来说,这时候需要有一个引路明灯,避免走弯路,提高学习效率。而书籍就扮演着这样的角色。一本好的…...
C#中各种循环遍历的功能与应用
在C#编程中,循环遍历是一种重要的技巧,它使我们能够有效地处理集合、数组和其他数据结构。本文将深入探讨C#中常见的循环遍历方式,包括for循环、foreach循环、while循环和do while循环,并给出它们在实际应用中的使用场景、示例和最…...
【必看技巧】Access开发者必备:如何用代码隐藏功能区、导航区、状态栏?
hi,大家好呀! 今天想着给大家分享点啥呢?最近几个月断更的有些“勤快”了,那就给大家分享个几行代码。 当我们在access中开发完成后,为了让我们的系统更加的像一个系统,我们会把access的功能区࿰…...
领先一步,效率翻倍:PieCloudDB Database 预聚集特性让查询速度飞起来!
在大数据时代,如何有效地管理和处理海量数据成为了企业面临的核心挑战。为此,拓数派推出了首款数据计算引擎 PieCloudDB Database,作为一款全新的云原生虚拟数仓,旨在提供更高效、更灵活的数据处理解决方案。 PieCloudDB 的设计理…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
