ARM编译空间属性(转)

原文地址:http://www.cnblogs.com/hongzg1982/articles/2205093.html

1. 程序的空间属性

一般情况下,一个程序本质上都是由 bss段、data段、text段三个组成的——本概念是当前的计算机程序设计中是很重要的一个基本概念。而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配,存储单元占用空间大小的问题。

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

(stack):栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载。而bss段不在可执行文件中,由系统初始化。

bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。 data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。 DATA段包含经过初始化的全局变量以及它们的值。 BSS段的大小从可执行文件中得到,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含DATA和BSS段的整个区段此时通常称为数据区。

2. ARM的image属性

ARM程序的组成
此处所说的“ARM程序”是指在ARM系统中正在执行的程序,而非保存在ROM中的bin映像(image)文件,这一点清注意区别。
一个ARM程序包含3部分:RO,RW和ZI
RO是程序中的指令和常量
RW是程序中的已初始化变量
ZI是程序中的未初始化的变量
Image文件包含了RO和RW数据。但不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。

烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。因此就有必要了解ARM程序是如何从ROM中的image到达实际运行状态的。
实际上,RO中的指令至少应该有这样的功能:
1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。
ARM C中的指令以及常量被编译后是RO类型数据。
ARM C中的未被初始化或初始化为0的变量编译后是ZI类型数据。
ARM C中的已被初始化成非0值的变量编译后市RW类型数据。

.text段是代码段。它用来放程序代码(code)。它通常是只读的(程序代码,编译好了就确定了,不可能改来改去的嘛)。

.data段是数据段。它用来存放初始化了的(initailized)全局变量(global)和初始化了的静态变量(static)。它是可读可写的。

.bss段是全局变量数据段。它用来存放未初始化的(uninitailized)全局变量(global)和未初始化的静态变量(static)。它也是可读可写的。bss是英文Block Started by Symbol的缩写。之所以把bss跟data分开来,是因为系统会为这些bss段的变量的初值清零。

.constdata段是常量数据段。它用来存放常量(const)。它也是只读的。

源程序中使用malloc分配的内存就是bss这一块,它的大小不是根据data的大小确定的,主要是由程序中同时分配内存最大值所确定的,不过如果超出了范围,也就是分配失败,可以等空间释放之后再分配。

以上这些段,用户可以非常灵活的定义其首地址和大小。但对大部分用户来说,程序代码区在ROM或FLASH中,可读写区域在SRAM或DRAM中。考虑一下自己程序规模,函数调用规模,内存使用大小,然后,参照一个连接定位文件,稍加修改就可以了

stack就是通常我们所说的堆栈。它用来保存函数的局部变量和参数。其操作方式类似于数据结构中的栈,是一种“后进先出”(Last In First Out,LIFO)的数据结构。这意味着最后放到栈上的数据,将会是第一个从栈上移走的数据,对于哪些暂时存储的信息,和不需要长时间保存的信息来说,LIFO这种数据结构非常理想。在调用函数或过程后,系统通常会清除栈上保存的局部变量、函数调用信息及其它信息。栈的顶部通常在可读写的RAM区的最后,其地址空间通常“向下减少”,即当栈上保存的数据越多,栈的地址就越小。

heap就是通常我们说的动态内存分配。它用来管理动态内存的。其操作方式跟数据结构中的堆,是不同的。

在ARM的集成开发环境中,

1、只读的代码段称为Code段,即上述的.text段。

2、只读的常量数据段,被称作RO Data段,即上述的.constdata段。

以上两个段统称为RO段(Read Only),放在ROM或FLASH等非易失性器件中。

3、可读可写的初始化了的全局变量和静态变量段,被称作RW Data段(ReadWrite),即上述的.bss段。

4、可读可写的未初始化的全局变量和静态变量段,被称作ZI Data段(Zero Init),即上述的.data段。因为这个段里的变量要被初始化为零,所以叫ZI段。

以上两个段统称为RW段,而在运行时,它必须重新装载到可读可写的RAM中。

时间: 2024-10-07 10:11:00

ARM编译空间属性(转)的相关文章

Oracle中分区表中表空间属性

Oracle中的分区表是Oracle中的一个很好的特性,可以把大表划分成多个小表,从而提高对于该大表的SQL执行效率,而各个分区对应用又是透明的. 分区表中的每个分区有独立的存储特性,包括表空间.PCT_FREE等.那分区表中的各分区表空间之间有什么关系?新建的分区会创建在哪个表空间中呢?对应的local分区索引又会使用哪个表空间呢?下面使用一个例子来解释上面的这些问题. 创建测试分区表: [email protected]>create table t (id number,name varc

自定义控件如同系统控件:自定义控件,画空间图片,定义空间属性,构造监听器。

android的基本控件很难满足用户的需求,因此有时候用户需要根据美工设置的一些图片来自定义一些控件,不多说,现在介绍一下,自定义一个开关控件的流程,让大家更了解控件的工作原理: 1.首先构建一个控件的类,继承view,这时候需要覆写view的构造方法.同时需要把美工美化好的图片拖到drawable目录下,为了能够手工写代码构建这个控件,则需要传入构建这个空间的上下文环境,即Context,并在构造方法里初始化这个类成员变量.在控件初始化的时候需要加载进美工的图片即:背景bg和开关滑动钮swic

『ORACLE』 表空间属性(11g)

查询表空间相关属性: select tablespace_name,contents,status,status,block_size from dba_tablespaces;   select file_name,tablespace_name,autoextensible,bytes    from dba_data_files;

ARM 编译工具keil 和 IAR 命令行编译和下载

目的 不管是Keil还是IAR对代码补全,高亮等编辑功能支持的不是很好,虽然现在的Keil 5.25对界面的支持好了很多,但是很多人还是青睐于第三方的编辑器,命令行的编译方式可以让我们在使用第三方编辑器编辑的时候进行代码编译和下载,通常我们比较喜欢的编辑器有下面一些,不是很全. _____________________________________ 常用的第三方编辑器介绍 Visual Studio 2010 - 2017 Windows 下面的VS工具配上番茄助手写代码爽的不得了,并且现在

Linux XT工业级操作系统-LXT5架构(ARM编译2015版本)

                      Linux XT工业级操作系统-LXT5架构组成                        系统模块                                                             简介                   U-Boot启动 引导程序(Bootloader)     Linux内核 Kernel内核(Linux)     Linux驱动 接口.设备驱动(Xdrv)     Ramdisk.gz

ARM汇编指令汇总

1.ARM汇编的格式:    在ARM汇编里,有些字符是用来标记行号的,这些字符要求顶格写:有些伪码是需要成对出现的,例如ENTRY和END,就需要对齐出现,也就是说他们要么都顶格,要么都空相等的空,否则编译器将报错.常量定义需要顶格书写,不然,编译器同样会报错.    2.字符串变量的值是一系列的字符,并且使用双引号作为分界符,如果要在字符串中使用双引号,则必须连续使用两个双引号.    3.在使用LDR时,当格式是LDR r0,=0x022248,则第二个参数表示地址,即0x022248,同

C预编译, 预处理, C/C++头文件, 编译控制,

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征.依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的. 其格式一般为: #Pragma Para 其中Para 为参数,下面来看一些常用的参数. (1)message 参数. Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输

GNU ARM 汇编指令

http://blog.chinaunix.net/u2/87718/showart_1683402.html GNU ARM 汇编指令简介第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C++编写程序很方便,但汇编源程序用于系统最基本的初始化,如初始化堆栈指针.设置页表.操作 ARM的协处理器等.初始化完成后就可以跳转到C代码执行.需要注意的是,GNU的汇编器遵循AT&T的汇编语法,可以从GNU的站点(www.gnu.org)上下载有关规范. 一. Linux汇编行结构任何汇编行

学习笔记TF062:TensorFlow线性代数编译框架XLA

XLA(Accelerated Linear Algebra),线性代数领域专用编译器(demain-specific compiler),优化TensorFlow计算.即时(just-in-time,JIT)编译或提前(ahead-of-time,AOT)编译实现XLA,有助于硬件加速.XLA还在试验阶段.https://www.tensorflow.org/versions/master/experimental/xla/ . XLA优势.线性代数领域专用编译器,优化TensorFlow计算