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 的设计理…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...