随便找个IAR或者其他编译器生成的map文件。我们不难发现程序就是 .txt, .bss, .data等段的集合。
再仔细一看,BL _main,_main是一个地址,.data段也有地址。这些地址是如何来的呢?
编译器地址空间:
编译器按照一定的地址空间来编译程序,最终的程序就是指令和地址的集合,这个地址空间就是编译器地址空间。
CPU统一寻址空间:
CPU按照统一编址的地址去访问相关数据或者硬件。
编译地址空间和物理地址空间要对上号才能正确运行。为什么呢?
如:BL _main(0x800000000). 这条是编译器编译出来指令,就是跳转到0x80000000,
假如执行完上述指令,cpu pc指针指向0x80000000,而该处没有指令,而是一个寄存器的地址,那么程序是没有办法执行的下去的。
如何实现编译地址空间和物理地址空间要对上号?
通过两种方法来实现
1:一种是编译时确定,就是给编译器设定参数比如某个段从某个地址开始编译。
一般如嵌入式中常见的从0x8000000, 0x2000000.或者你可以单独定义数据段从某个地址开始。
然后通过bootloader 或者PC端载入程序把程序载入到对应的地址运行。
这种方式适合没有mmu的嵌入式系统的编译和载入。尤其要求载入的物理地址必须与代码段编译地址空间相对应(起始位置要相同)。
2: 通过MMU来实现地址的重定位。
编译器不关心的物理地址,编译器把编译地址认为从0-4g进行统一编址。
每个elf文件被载入内存,首先确定其载入内存所在的地址作为基地址,或者说将elf文件映射到对应的空间中。