首页 > 其他 > 详细

GNU LD之一LMA和VMA

时间:2015-11-19 23:48:28      阅读:410      评论:0      收藏:0      [点我收藏+]

MIPS 处理器存储器结构

项目当中使用的是一颗MIPS CPU,存储空间是标准的MIPS内存分配,内存被划分为几个部分,概括如下:

Boot room, boot code存储空间;

iram, code 存储空间;

dram,data存储空间;

也就是说code和data有各自独立的存储空间,分开放置。

我们平常用gcc和ld生成一个可执行文件的时候,例如在命令行输入gcc -o test test.c,生成的可执行文件是一个文件哦,也就是说code和data都在一份可执行文件里面。我们把这份可执行文件烧写到flash里面,然后cpu再从flash里面取指令执行。

可是在前面,我们明明规划了code和data都各自独立的存储空间啊。有心人会问,是的啊,你讲的没错,可是这是怎么一回事呢?

两种处理器架构的区别

好,那我们回到开始,先从为什么会有code和data各自规划一块存储空间的概念。这其实得从“冯诺依曼结构”和“哈佛”结构说起。

“冯诺依曼结构”,是指程序和数据存储空间并不是分开的,而是在一块存储器里面,所以程序和数据的访问位宽是相等的。

“哈佛结构”,是指程序和数据存储空间是分开的,各自有一块存储器,所以程序和数据的访问位宽可以不相等。

现在的处理器基本上都是属于上面2种架构,例如x86, arm, mips等。

说完这个,一切都清楚了。对了,我所用的MIPS恰好是“哈佛结构”的啰!

LMA和VMA

那么“哈佛结构”的处理器,明明生成的可执行文件,也就是通常所说的bin文件,只有一份啊,所以程序和数据都在同一份bin文件的,例如test.bin。我们将test.bin烧入到flash之后。

在哈佛架构的处理器上,这份可执行文件是怎么执行的呢?

好问题。

我们知道对于一个C程序,在其编译链接时,代码会放在text段,常量是存储在rodata段,初始化的全局变量或者初始化的静态变量的值会放在data段,未初始化的全局变量或者静态变量会放在bss段。

而字符串指针变量例如char *string = "abcdef",字符串"abcdef"是存储在const段,string这个指针变量的值为字符串"abcdef"的地址,也就是rodata段中的某个地址。

text段和rodata段,都是存放在room中,而data和bss开始是存放在bin file中,但在C程序的main函数开始跑之前,是需要被搬运到RAM中的。

所以我们需要在bootloader中,用汇编语言写一段代码,将bin file中的data段copy到RAM中,bss段不必搬,只需要将bss段在RAM中的地址区间清零就可以了。

然后再将sp指针指向RAM的最高地址就可以了。

在这个搬运的过程中,就会运用到LMA和VMA了。

LMA就是load address,也就是加载地址;

VMA就是virtual address,也就是运行地址。

具体是什么意思。例如我们刚才讲到的test.bin,那么程序和数据都会按顺序存储在里面啊,顺序请参考http://www.cnblogs.com/ironx/p/4954845.html中的“目标文件在其存储器映像文件中的布局”。

在那篇文章的对应章节中,描述的就是LMA,也就是程序和数据在bin文件中的存储地址,VMA也就是data和bss段在RAM中的运行地址。

而我们在bootloader中的汇编代码里面,需要将data段copy到RAM中,并清零bss段。

这个时候,汇编代码会把数据从其LMA处,copy到VMA处,也就是从bin文件的存储地址复制到RAM中的运行地址处。

一个典型的bootloader搬运代码如下所示:

 

既然bootloader会用到LMA和VMA,那么LMA和VMA在哪里定义呢,就是在ld脚本中啦,ld脚本就规定程序和数据在bin文件里面是什么存储的,以及运行时在rom和ram中是怎么存储的文件。

请参考http://www.cnblogs.com/ironx/p/4954845.html

 

GNU LD之一LMA和VMA

原文:http://www.cnblogs.com/ironx/p/4963018.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!