GNU LD之一LMA和VMA

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

时间: 2024-12-31 03:26:32

GNU LD之一LMA和VMA的相关文章

GNU LD 脚本学习笔记

LD脚本(linker script)是什么 GNU ld是链接器,ld实际并不是GCC的一部分,ld属于binutils软件包.但是嵌入式开发时,下载的linaro GCC工具集中是包含 arm-linux-gnueabihf-ld 的.工作中我经常使用ARM的scatter文件,和这个LD脚本差不多,只不过scatter文件的功能要弱不少,这也是为什么ARM6中armclang也是推荐使用 GNU LD脚本的原因,ARM也不想维护自己特有的编译器了,只要专心把clang bytecode翻译

LMA(装载内存地址)与VMA(虚拟内存地址)

      关于LMA和VMA,这个问题,有点点小复杂,不过,此处,我会把我的理解,尽量通过通俗的方式解释出来,以方便理解.当然,鄙人水平有限,难免有错,希望各位批评指正.       一般提及LMA和VMA,多数情况都是和ld,链接器相关的.在了解这两个名词的详细含义之前,有些基本知识和前提要说一下: [基础知识] 1.从你写的源代码到执行你的程序,一般经历了这几个过程:源代码编辑 -> 编译 -> 链接 -> 装载 -> 执行 2.编译,简单说就是用编译工具,将你的源码,变成可

链接脚本之LMA VMA解释

链接脚本中的LMA和VMA是什么意思.这个问题纠结了一段时间,今天在看<ARM体系结构与编程>时,豁然开朗,写下自己的认识.分享例如以下: LMA:载入地址 位于存储器中的地址  LOAD MEMORY ADDRESS VMA:执行地址(虚拟地址) 执行时的地址 VIRTUAL MEMORY ADDRESS  为什么用VMA表示呐?由于cpu执行的地址都是虚拟地址,经过MMU转为物理地址.在没有开MMU的裸板下,延续了这一称呼.理解为执行地址. 为什么要分 两种地址? 执行映像文件时,有些域能

ld 脚本浅析-LD手册粗糙翻译

本文乃转载, 我在其基础上做了少量修改. 原作者的E-mail是[email protected] 完成于2005.11.5-2005.11.8 0. Contents 1. 概论2. 基本概念3. 脚本格式4. 简单例子5. 简单脚本命令6. 对符号的赋值7. SECTIONS命令8. MEMORY命令9. PHDRS命令10. VERSION命令11. 脚本内的表达式12. 暗含的连接脚本 1. 概论 每一个链接过程都由链接脚本(linker script, 一般以lds作为文件的后缀名)控

GNU make 总结 (五)

一.使用make更新静态库 静态库文件是一些.o文件的集合,在Linux中使用ar工具对它进行维护管理.一个静态库通常由多个.o文件组成,这些.o文件可独立的被作为一个规则的目标,库成员作为目标时需要按照如下格式来书写: ARCHIVE(MEMBER) 注:这种格式只能出现在规则的目标和依赖中,不能出现在命令行中.含有这种表达式的规则的命令行只能是ar命令或者其它可以对库成员进行操作的命令.如下规则用于创建库“foolib”,并将“hack.o”成员加入库中: foolib(hack.o) :

[转]Linux下的链接脚本基础

[转]http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml 1. 前言 每一个链接过程都由链接脚本(linker script, 一般以lds作为文件的后缀名)控制. 链接脚本主要用于规定如何把输入文件内的section放入输出文件内, 并控制输出文件内各部分在程序地址空间内的布局. 但你也可以用连接命令做一些其他事情.连接器有个默认的内置连接脚本, 可用ld –verbose查看. 连接选项-r和-N可以影响默

GNU-ld链接脚本浅析

http://blogold.chinaunix.net/u/30686/showart_357384.html 本文乃转载, 我在其基础上做了少量修改. 原作者的E-mail是[email protected].ac.cn. 完成于2005.11.5-2005.11.8 0. Contents 1. 概论2. 基本概念3. 脚本格式4. 简单例子5. 简单脚本命令6. 对符号的赋值7. SECTIONS命令8. MEMORY命令9. PHDRS命令10. VERSION命令11. 脚本内的表达

Linux下的lds链接脚本详解【转】

转自:http://www.cnblogs.com/li-hao/p/4107964.html 转载自:http://linux.chinaunix.net/techdoc/beginner/2009/08/12/1129972.shtml 一. 概论 每一个链接过程都由链接脚本(linker script, 一般以lds作为文件的后缀名)控制. 链接脚本主要用于规定如何把输入文件内的section放入输出文件内, 并控制输出文件内各部分在程序地址空间内的布局. 但你也可以用连接命令做一些其他事

make的使用和Makefile规则和编程及其基本命令(简单)

转自:http://blog.chinaunix.net/uid-23929712-id-2650328.html 概述: make从Makefile中文件中获取模块间的依赖关系,判断哪些文件已经过时,根据这些信息make确定哪些文件需要重新编译,然后使用Makefile中的编译命令进行编译 make命令参数详解 -C dir:在读取Makefile文件前,先切换到"dir"目录下,也就是把dir作为当前目录 -d     :make执行时打印出所有的调试信息 -e     :不允许在