当前位置: 首页 > news >正文

单片机启动文件——数据段重定位,BSS段清零

目录

    • 重定位概念的引入
      • 一、数据段重定位
        • 1.作用:
        • 2.目的:
        • 3.自己模拟代码
      • 二、BSS段清零
        • 1.作用:
        • 2.目的:
        • 3.自己模拟代码
      • 三,实现原理

重定位概念的引入

单片机中内存段的详细介绍
在单片机中内存分为了很多不同的区域,在上面的文章中可以看到,flash与RAM中有两段空间的信息在flash与RAM都保持了,分别是RWdata段与bss段,在启动文件中对这两块区域分别进行了数据段重定位与BSS段清零,而对应的代码是由编译器根据散列文件自动生成的,我们看不到,但是我们可以不让编译器自动生成自己进行数据段重定位与BSS段清零

数据段重定位与BSS段清零对应的代码是由编译器根据散列文件自动生成的,我们看不到,我们可以通过反汇编文件以及Debug时的反汇编窗口看到编译器给我们生成的代码如何让keil编译生成bin文件与反汇编文件?,同时我们可以不让编译器自动生成自己进行数据段重定位与BSS段清零
操作方法就是
1.不使用main的函数名,使用其它函数名
在这里插入图片描述
在这里插入图片描述

一、数据段重定位

1.作用:
  • 将.data段从非易失性存储器(如Flash/ROM)复制到易失性存储器(RAM)中的目标位置。

  • 链接器在编译链接阶段,会将已初始化的全局变量和静态变量放入.data段,并将它们的初始值存储在Flash中。

  • 但是程序运行时,这些变量必须位于RAM中才能被修改。

  • 启动文件负责将存储在Flash中的初始值数据“搬运”到RAM中对应变量的地址处。

2.目的:
  • 确保初始化变量拥有正确的初始值:如果.data段没有从Flash复制到RAM,那么所有初始化为非零值的全局变量和静态变量在程序启动时将处于未定义状态(RAM上电后的值是随机的),而不是程序员设定的初始值。这会导致程序行为完全不可预测。

  • 满足C/C++语言规范要求:C/C++标准规定全局变量和静态变量必须在程序启动时完成初始化(如果有初始值)。重定位是实现这一语言要求的底层机制。

  • 实现变量的可写性:Flash通常是只读的(在运行时),而变量需要被程序读写。将初始值复制到RAM中是变量可写的先决条件。

3.自己模拟代码
/*启动文件模拟过程代码*/IMPORT |Image$$RW_IRAM1$$Base|IMPORT |Image$$RW_IRAM1$$Length|IMPORT |Load$$RW_IRAM1$$Base|LDR R0, = |Image$$RW_IRAM1$$Base|    ; DESTLDR R1, = |Load$$RW_IRAM1$$Base|     ; SORUCELDR R2, = |Image$$RW_IRAM1$$Length|  ; LENGTH //根据ARM架构AAPCS法则模拟函数参数BL My_Copy	 
/*C语言实现拷贝逻辑*/				 
void My_Copy(char* const Destination,char* const Soruce,int Size)
{int i = 0;for(;i < Size;i ++){Destination[i] = Soruce[i];}return;
}

二、BSS段清零

1.作用:
  • 将.bss段在RAM中对应的内存区域全部填充为0。

  • 链接器将未初始化或显式初始化为0的全局变量和静态变量放入.bss段。.bss段在程序映像(存储在Flash中)中不占用实际存储空间,它只记录需要在RAM中预留多少空间以及起始地址。

  • 启动代码需要找到.bss段在RAM中的起始地址和长度,然后将这块内存区域清零。

2.目的:
  • 确保未初始化的变量从0开始:C/C++标准规定未显式初始化的全局变量和静态变量在程序启动时必须被初始化为0(对于基本类型是0,对于指针是NULL)。如果不清零.bss段,这些变量在启动时将包含RAM上电后的随机垃圾值,导致程序行为不可预测,尤其是指针变量可能指向非法地址。

  • 节省Flash存储空间:由于.bss段中的变量初始值都是0,没有必要在Flash中存储一大串0值。启动时直接清零对应的RAM区域是更高效的方法(空间换时间)。

  • 满足语言规范要求:与.data段重定位一样,BSS清零是实现C/C++语言对未初始化/零初始化全局变量和静态变量初始化要求的底层机制。

3.自己模拟代码
/*启动文件模拟过程代码*/IMPORT |Image$$RW_IRAM1$$ZI$$Base|IMPORT |Image$$RW_IRAM1$$ZI$$Length|	LDR R0, = |Image$$RW_IRAM1$$ZI$$Base|   ; DESTLDR R1, = 0                             ; SORUCE LDR R2, = |Image$$RW_IRAM1$$ZI$$Length| ; LENGTH BL My_Zero_Init	//根据ARM架构AAPCS法则模拟函数参数BL My_Zero_Init
/*C语言实现清零逻辑*/				 
void My_Zero_Init(char* const Destination,int Soruce,int Size)
{int i = 0;for(;i < Size;i ++){Destination[i] = Soruce;}return;
}

三,实现原理

C语言-》编译器-》机器码(汇编就是机器码的注释)
展开能力,C语言与汇编的后沟就是编译器,C语言是编程工具,汇编语言是结果
判断结果是否符合预期?学会看反汇编
如何控制结果符合预期?学会一定的C语言语法以及编译器的工作特性

针对keil平台,控制编译器的方法就是分散加载文件
我们可以通过分散加载文件的语法来控制代码函数变量的链接地址
理论上也可以控制加载地址针对使用烧录器来说因为烧录器使用的是hex文件包含程序烧录的地址信息,但是一般来说程序编译后使用bin二进制文件这个文件使用特定的烧录工具,烧录的是纯机器码即代码指令不包含代码加载地址信息。
分散加载的语法可以参考分散加载文件与attribute关键字使用说明
同时分散加载文件中也包含一些符号信息,我们在代码中可以使用特定的语法来引入这些符号的值,RW-data段的加载地址大小,搬运的目的地址,同理bss段数据也是同理。
导入符号的方法有

/*汇编文件使用*/IMPORT |Image$$ER_IROM1$$Base|IMPORT |Image$$ER_IROM1$$Length|IMPORT |Load$$ER_IROM1$$Base|IMPORT |Image$$RW_IRAM1$$Base|IMPORT |Image$$RW_IRAM1$$Length|IMPORT |Load$$RW_IRAM1$$Base|IMPORT |Image$$RW_IRAM1$$ZI$$Base|IMPORT |Image$$RW_IRAM1$$ZI$$Length|	
/*C语言文件使用*/extern int Image$$ER_IROM1$$Base;extern int Image$$ER_IROM1$$Length;extern int Load$$ER_IROM1$$Base;extern int Image$$RW_IRAM1$$Base;extern int Image$$RW_IRAM1$$Length;extern int Load$$RW_IRAM1$$Base;extern int Image$$RW_IRAM1$$ZI$$Base;extern int Image$$RW_IRAM1$$ZI$$Length;	extern int Image$$ER_IROM1$$Base[];extern int Image$$ER_IROM1$$Length[];extern int Load$$ER_IROM1$$Base[];extern int Image$$RW_IRAM1$$Base[];extern int Image$$RW_IRAM1$$Length[];extern int Load$$RW_IRAM1$$Base[];extern int Image$$RW_IRAM1$$ZI$$Base[];extern int Image$$RW_IRAM1$$ZI$$Length[];	extern int * Image$$ER_IROM1$$Base;extern int * Image$$ER_IROM1$$Length;extern int * Load$$ER_IROM1$$Base;extern int * Image$$RW_IRAM1$$Base;extern int * Image$$RW_IRAM1$$Length;extern int * Load$$RW_IRAM1$$Base;extern int * Image$$RW_IRAM1$$ZI$$Base;extern int * Image$$RW_IRAM1$$ZI$$Length;	

文章转载自:

http://GHf3azop.dwfst.cn
http://JgJHxoTp.dwfst.cn
http://CvP8lkn1.dwfst.cn
http://P9guBzub.dwfst.cn
http://5kcrQxMj.dwfst.cn
http://AvDayVaN.dwfst.cn
http://DdgEIXFc.dwfst.cn
http://zjU5Rz0j.dwfst.cn
http://HfaCU5sm.dwfst.cn
http://1M5j7O0N.dwfst.cn
http://gRlqz3m3.dwfst.cn
http://N7laf1m3.dwfst.cn
http://wRUMFV48.dwfst.cn
http://0cqtAZ0p.dwfst.cn
http://xK35p4X2.dwfst.cn
http://MvhiILDX.dwfst.cn
http://JobyQE86.dwfst.cn
http://ygZsqU4m.dwfst.cn
http://HdTf5FOI.dwfst.cn
http://IOiy2wpz.dwfst.cn
http://P6QGDAWs.dwfst.cn
http://sb1Icu2V.dwfst.cn
http://CZFhZr9I.dwfst.cn
http://rRBHGZlf.dwfst.cn
http://rGCbekBB.dwfst.cn
http://flZGbbsm.dwfst.cn
http://gr4uhhoG.dwfst.cn
http://ZGEn0NWQ.dwfst.cn
http://0pGfWuo8.dwfst.cn
http://SpFQVPuS.dwfst.cn
http://www.dtcms.com/a/377044.html

相关文章:

  • [xboard]ARM汇编基础学习
  • rv1126bp之mipi sensor驱动
  • 手机上可以记录每日工作计划的待办提醒工具?
  • 今天开始我们学习安全管理模块Linux防火墙
  • 反爬API接口:技术实现与应用场景
  • 10.3 马尔可夫矩阵、人口和经济
  • OpenResty 中实现限流(Rate Limiting)的实战案例
  • 告别“人肉API”时代:AI智能体如何重构人机协同新范式
  • Centos7部署ceph存储
  • 【Pywinauto库】10.1 pywinauto.base_wrapper控件
  • 机器人/人形机器人无法商业化落地的原因
  • 十一旅游气象的关键影响与“用大模型拿到更好天气数据”的落地路线
  • 软考系统架构设计师之软件测试篇
  • 【竞赛系列】机器学习实操项目04——客户信用评估模型开发全流程(baseline)
  • 爆破mysql登录密码
  • PG-210-HI 山洪预警系统呼叫端:筑牢山区应急预警 “安全防线”
  • 工业 CT 检测服务公司转型:扫描图像 AI 重构系统与客户检测需求智能匹配中台
  • 【CVPR2021】《Unbiased mean teacher for cross-domain object detection》译读笔记
  • AI时代技术面试重构:谷歌如何用Vibe Coding与抗作弊革命重塑招聘
  • 【Python/Pytorch】-- 贝叶斯定理
  • .NET Framework 和 .NET 的核心差异
  • Spring组件注解详解:@Component、@Service、@Repository、@Controller
  • STM32初始化串口重定向后printf调试信息不输出的问题
  • Monorepo 全面解析:优势、挑战与适用场景
  • 领码方案|Linux 下 PLT → PDF 转换服务超级完整版:异步、权限、进度(一气呵成)
  • TCP内网穿透:将局域网内部的TCP/HTTP服务暴露在公网上
  • day40 SQLite3单词查询程序设计与实现
  • 华为FreeBuds 7i其他手机能用空间音频吗?如何开启?
  • Java — Lambda 表达式与函数式接口解析
  • Apache Commons Math3 使用指南:强大的Java数学库