打印
[其他]

Cortex-M3 ARM代码编译,链接与启动过程深度分析

[复制链接]
楼主: 米多0036
手机看帖
扫描二维码
随时随地手机跟帖
41
米多0036|  楼主 | 2022-12-31 13:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
​ 上面的脚本定义了一个段叫data,里面包含了所有Objects文件中的data段,不同文件中定义的全局变量和静态变量全部汇聚到了这一个段中。里面还定义了一些label,这些label其实就是映像文件中各个数据或者段的地址(Address/Offset),主要用于给程序提供这些地址信息,让程序对映像文件中的这些资源进行处理。你像这个data段,需要在startup初始化阶段将data段从FLASH 复制到RAM中。既然要复制,那程序就需要知道源地址,目的地址以及要复制的长度。开始地址就是data段在整个映像的Offset地址,在这里起了个名字叫_sdata,结束地址叫_edata,知道了开始地址和结束地址也就知道了信息源的所有信息(开始地址、结束地址、长度)。那目的地址在哪?别着急,目的地址的设置是使用了 AT 这个指令,意思就是告诉链接器这段内容是需要搬运的,下载地址和运行地址是不一样的。

使用特权

评论回复
42
米多0036|  楼主 | 2022-12-31 13:58 | 只看该作者
  .fini_array :
  {
......
......
  } >FLASH
/* used by the startup to initialize data */
  _sidata = .;

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : AT ( _sidata )

使用特权

评论回复
43
米多0036|  楼主 | 2022-12-31 13:58 | 只看该作者
上面的指令意思是这个段的实际链接地址是 RAM 这个Memory Region中定义的0x20000000开始的地方,根据内容依次往后放。但现在在映像中实际的位置是FLASH 这个Memory Region中定义的0x08000000开始的地方开始放置的,根据内容依次顺序放置的。在FLASH中这个内存域中,前面可能已经放置了启动代码和其他代码段。使用了这个说明后,产生的效果是在映像文件中是连续存放的内容(以0x08000000作为基地址),但是data段实际的链接地址都是以0x20000000作为基地址的。比如你定义了一个全局变量 int A = 88;,它实际运行的地址在0x20000010这个地址,但是在最开始整个映像都在FLASH中,它可能在映像中的实际存在位置为0x08000100。在程序最开始(还没用到这个全局变量之前)的代码中需要将data段整体地从FLASH中移动到RAM中。如果不用**AT**指令的话,映像文件会直接按照链接地址生成,就意味着映像文件会很大,因为代码段0x08000000和数据段0x20000000之间有一个Gap,这个Gap需要使用大量的0来填充。想想都觉着这个映像很大。 ​

使用特权

评论回复
44
米多0036|  楼主 | 2022-12-31 13:59 | 只看该作者
咱们在对应的map文件中能找到.data

使用特权

评论回复
45
米多0036|  楼主 | 2022-12-31 14:00 | 只看该作者
.fini_array     0x08004aa8        0x4
                0x08004aa8                PROVIDE (__fini_array_start = .)
*(.fini_array*)
.fini_array    0x08004aa8        0x4 d:/toolchain/msys64/mingw32/bin/../lib/gcc/arm-none-eabi/10.1.0/thumb/v7-m/nofp/crtbegin.o
*(SORT_BY_NAME(.fini_array.*))
                0x08004aac                PROVIDE (__fini_array_end = .)
                0x08004aac                _sidata = .

.data           0x20000000      0x848 load address 0x08004aac
                0x20000000                . = ALIGN (0x4)
                0x20000000                _sdata = .
*(.data)

使用特权

评论回复
46
米多0036|  楼主 | 2022-12-31 14:01 | 只看该作者
意思表示data段数据存储在FLASH,从_sidata源地址0x08004aac开始,data段长度为0x848,拷贝到目的地址为0x20000000。

使用特权

评论回复
47
米多0036|  楼主 | 2022-12-31 14:02 | 只看该作者
heap和stack
  .heap :
  {
    . = ALIGN(8);
    __end__ = .;
    PROVIDE(end = .);
    PROVIDE(_end = .);
    PROVIDE(__end = .);
    __HeapBase = .;
    . += _minimum_heap_size;
    __HeapEnd = .;
    __heap_end = .;
  } >RAM

  .stack :
  {
    . = ALIGN(8);
    . += _minimum_stack_size;
  } >RAM

  /* Define the stack.  The stack is full descending so begins just above last byte
   of RAM.  Note that EABI requires the stack to be 8-byte aligned for a call. */
  _estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
  _sstack = _estack - _minimum_heap_size;
  PROVIDE(__stack = _estack);

使用特权

评论回复
48
米多0036|  楼主 | 2022-12-31 14:03 | 只看该作者
下面两个图形象的描述DATA段,堆和栈在RAM空间分布情况:

使用特权

评论回复
49
米多0036|  楼主 | 2022-12-31 14:03 | 只看该作者
简单举个函数调用的例子帮助大家理解堆和栈原理。

使用特权

评论回复
50
米多0036|  楼主 | 2022-12-31 14:57 | 只看该作者
在图中C文件中,全局变量global_variable,静态变量static_variable和函数内部的静态变量local_static_variable都属于全局变量存在Static区域。函数入参和内部的临时变量会被压入.stack区域。函数中malloc获取到的内存从.heap区域中获取。

使用特权

评论回复
51
米多0036|  楼主 | 2022-12-31 14:59 | 只看该作者
那么Stack和Heap有什么区别呢?如下图:

使用特权

评论回复
52
米多0036|  楼主 | 2022-12-31 14:59 | 只看该作者

使用特权

评论回复
53
米多0036|  楼主 | 2022-12-31 15:00 | 只看该作者
下图可以帮助大家理解Heap在应用中容易发生的问题。因为内存申请memory allocation是随机的,这样会导致Fragmented Heap。如果Stack和Heap没有界限保护的会导致Stack Crash。

使用特权

评论回复
54
米多0036|  楼主 | 2022-12-31 15:01 | 只看该作者

使用特权

评论回复
55
米多0036|  楼主 | 2022-12-31 15:02 | 只看该作者
总结
​ 暂时就讲这么多了。不过应该够帮助大家去解密CotrexM3 ARM的代码运行原理。这样你的代码如何跑,跑在哪里完全支配你的手中。本文可能有些描述不准确、不合理或有误的地方,希望多多指正。我会尽量完善,至于有些不够详尽的地方会在后面找时间填补上。

使用特权

评论回复
56
tpgf| | 2023-1-4 08:51 | 只看该作者
编译(compilation , compile) 1、利用编译程序从源语言编写的源程序产生目标程序的过程。 2、用编译程序产生目标程序的动作

使用特权

评论回复
57
nawu| | 2023-1-4 09:41 | 只看该作者
编译就是把高级语言变成计算机可以识别的2进制语言

使用特权

评论回复
58
drer| | 2023-1-4 10:02 | 只看该作者
词法分析的任务是对由字符组成的单词进行处理,从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。执行词法分析的程序称为词法分析程序或扫描器。

使用特权

评论回复
59
zljiu| | 2023-1-4 10:09 | 只看该作者
编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,按该语言使用的语法规则分析检查每条语句是否有正确的逻辑结构,程序是最终的一个语法单位。编译程序的语法规则可用上下文无关文法来刻画。

使用特权

评论回复
60
kxsi| | 2023-1-4 10:22 | 只看该作者
如果编译过程中发现源程序有错误,编译程序应报告错误的性质和错误的发生的地点,并且将错误所造成的影响限制在尽可能小的范围内,使得源程序的其余部分能继续被编译下去,有些编译程序还能自动纠正错误,这些工作由错误处理程序完成。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则