arm-none-eabi编译的程序结构和MCU运行时的程序结构

发布于:2024-04-24 ⋅ 阅读:(26) ⋅ 点赞:(0)

目录

概述

1 RT-Thread Studio创建STM32H7工程

1.1 下载RT-Thread Studio

1.2 编译STM32H7工程

2  编译文件结构

2.1 代码区( text segment)

2.2 静态数据/全局初始化数据区

2.3 未初始化数据区

3 MCU中代码运行时的数据结构

4 程序分段的意义


概述

本文主要讲述编译的代码文件的程序结构,以及在程序运行的过程中,各个代码段或者数据区在程序中加载的过程。还总结程序分段的内在含义。

1 RT-Thread Studio创建STM32H7工程

1.1 下载RT-Thread Studio

step - 1: 安装RT-Thread Studio

打开如下链接,下载RT-Thread Studio

https://www.rt-thread.org/document/site/#/development-tools/rtthread-studio/um/studio-user-begin

 下载页面如下:

step - 2: 创建工程

安装完成后,使用RT-Thread Studio创建STM32H7工程

step - 3: 创建完成工程后,打开工程

1.2 编译STM32H7工程

使用RT-Thread Studio编译STM32H7工程,编译成功后可以看见如下信息:

 编译log如下:

  arm-none-eabi-size --format=berkeley "rtthread.elf"
  text           data        bss        dec           hex        filename
  68960       1808       4552      75320      12638      rtthread.elf

使用如下列表,简单介绍以上数据的意义:

内容 名称 数据
代码区 text 68960
静态数据/全局初始化数据区 data 1808
未初始化数据区 bss 4552
十进制数据总和 dec 75320
十六进制数据总和 hex 12638
文件名称 filename rtthread.elf

2  编译文件结构

2.1 代码区( text segment)

该区域主要存放CPU执行的机器指令,通过代码区是可以共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁执行的程序,只需要在内存中有一份代码即可。代码区通常是只读的,使其只读的原因是防止意外的修改它的指令。另外,代码去还规划了局部变量的相关信息。

代码区的指令包括操作码和操作对象(或对象地址引用)。如果是立即数,就直接包含在代码中。如果是局部数据,将运行在栈区分配空间,然后在引用该数据的地址。如果是BSS区和数据区,在代码中同样将应用该数据的地址。

2.2 静态数据/全局初始化数据区

该区包含了在程序中明确被初始化的全局变量,已经初始化的静态变量和数据常量,如下两种情况将存放在数据区:

1) 定义一个全局变量:

int maxcont = 99;

这个变量将放在初始化数据区

2)任意位置的静态变量,也将存储到初始化数据区,例如:

static int val = 100;

2.3 未初始化数据区

该区域也被称为BSS区,存入的是全局为初始化的变量和为初始化的静态变量,BSS区的数据在程序开始执行之前被内核初始化为0或者空指针( NULL)。

3 MCU中代码运行时的数据结构

在运行非linux操作系统的通用型STM32芯片中,只有一个进程,就是上电后运行的总体程序代码。它包含:申请的内存空间,代码(代码段、数据段、BSS)、堆、栈。

1)代码区

加载是可执行文件的代码段,其加载到内存中的位置由加载器完成。加载代码由MCU内部的bootloader完成,这部分bootloader在芯片生产后已经固化在其内部了。

2)全局初始化数据区/静态数据区

MCU加载可执行文件的数据段时,这部分数据可位于代码段之后,也可以单独分开。程序在运行之初就为该数据段申请了空间,在程序退出时才释放。因此,存储于数据段(全局初始化、静态数据初始化)的数据生存周期为整个程序的运行过程

3)未初始化数据区(BSS)

加载可以执行型文件的BSS段,其位置可以分开,也可以紧靠近数据段,程序运行之初,就为该部分申请了空间。程序退出时才释放。因此,存储于该部分的数据(全局未初始化、金泰未初始化数据)的生存周期为整个程序的运行过程

4)栈区(stack)

由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行的过程中实时的加载和释放。因此,局部变量的生存周期为申请到释放该段栈空间的过程

5)堆区(heap)

用于动态内存分配,堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放。对于有内存管理的OS来说,OS会定期回收没有被释放且没有被使用的内存。

4 程序分段的意义

1)代码段和数据段分开,运行时便于分开加载。在哈佛结构体系的MCU将取得更好的流水线处理效率

2)代码是依次执行的,由处理器的PC指针依次读入,而且代码也可以被多个程序共享。数据在整个程序运行的过程中也将多次被使用,且数据是可变的,如果两者混在一起,造成内存的极大浪费。

3)临时数据及需要再次使用的代码在运行时放入栈中,生命周期短,便于提高资源的利用率

4)堆区可以有程序员分配和释放,以便用户自由分配,提高程序的灵活性