uboot 链接地址与运行地址的区别
对于ARM架构的CPU,上电后PC寄存器是指向0地址处的,从这个地址开始运行程序,那么运行了启动代码后会把程序搬移到内存中去运行,这样就是产生程序会在运行时有个两地址,而由源码编译为可执行文件时只会指定一个链接地址,指定的这个地址通常是在内存中运行时的运行地址,那么刚上电启动时的程序运行地址怎么办呐?这里要先介绍汇编语言中的位置无关码。
使用C/C++或者其他高级语言编程,最后会被编译器工具转换为汇编代码,最后再翻译成机器码存储在内存、硬盘或者其他存储器上。机器码的构造不同的CPU有不同的规则,在这里就不再讨论,我们去关注汇编代码。在嵌入式开发中汇编程序通常用于非常关键的地方,比如系统启动阶段,中断向量表等。在启动阶段会经常使用到b、bl两条跳转指令。这两条语句到时完成跳转的工作,但是bl在跳转时会将跳转处的地址存放在ARM的LR寄存器中,方便在后面跳转回来。在使用b或bl跳转时,下一条指令的地址是这样计算的:将指令中24位带符号的补码扩展为32位;将此32位数左移两位;将得到的值加入到PC寄存器中,即可得到跳转的目标地址。这样可以发现,b跳转指令依赖于当前PC寄存器的值,这个特性使得使用b指令的程序不依赖于代码存储的位置---即不管这条代码放在什么位置,b指令都可以跳到正确的位置,这类指令被称为位置无关码。
所以u-boot程序刚开始执行时,他所处的地址不等于运行地址,不管是norflash启动还是nandflash启动,刚开始运行都是从0地址,那么在开头就要先使用b、bl、mov等“位置无关”的指令完成将代码从Flash等设备中复制到内存的“运行地址”处,然后再跳到“运行地址去执行”。
那么程序的运行地址是哪,u-boot的程序是怎么组织的呢?由源码到可执行程序通常会经过这样几个步骤:预处理、编译、汇编、链接
最后的链接阶段通常使用arm-linux-ld选项用于将多个目标文件、库文件链接成可执行文件,其中“-T”选项,可以直接用它来指定代码段、数据段、bss段的起始地址,也可以用来指定一个链接脚本,在连接脚本里进行更复杂的地址设置。
1.直接指定代码段,数据段,BSS段的起始地址:
-Ttest startaddr -Tdata startaddr -Tbss startaddr
示例:arm-linux-ld –Ttext 0x0000000 led_on.o -o led_on_elf
他表示代码段的运行地址为0x0000000,由于没有定义数据段、bss段的起始地址他们依次被放在代码段的后面
2..使用连接脚本设置地址:arm-linux-ld -T u-boot.lds -o u-boot
这里的链接脚本就是u-boot.lds这个文件,它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。
先看一下 GNU官方网站上 对.lds文件形式的完整描述:
SECTIONS { ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr ) { contents } >region :phdr =fill ... } |
secname和contents是必须的,其他的都是可选的。下面挑几个常用的看看:
1、secname:段名
2、contents:决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)
3、start:本段连接(运行)的地址,如果没有使用AT(ldadr),本段存储的地址也是start。GNU网站上说start可以用任意一种描述地址的符号来描述。
4、AT(ldadr):定义本段存储(加载)的地址。
下面,结合u-boot.lds看看一个正式的连接脚本文件。
OUTPUT_FORMAT("elf32littlearm", "elf32littlearm", "elf32littlearm") ;指定输出可执行文件是elf格式,32位ARM指令,小端 OUTPUT_ARCH(arm) ;指定输出可执行文件的平台为ARM ENTRY(_start) ;指定输出可执行文件的起始代码段为_start. SECTIONS { . = 0x00000000 ; 从0x0位置开始 . = ALIGN(4) ; 代码以4字节对齐 .text : ;指定代码段 { cpu/arm920t/start.o (.text) ; 代码的第一个代码部分 *(.text) ;其它代码部分 } . = ALIGN(4) .rodata : { *(.rodata) } ;指定只读数据段 . = ALIGN(4); .data : { *(.data) } ;指定读/写数据段 . = ALIGN(4); .got : { *(.got) } ;指定got段, got段式是uboot自定义的一个段, 非标准段 __u_boot_cmd_start = . ;把__u_boot_cmd_start赋值为当前位置, 即起始位置 .u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在该段. __u_boot_cmd_end = .;把__u_boot_cmd_end赋值为当前位置,即结束位置 . = ALIGN(4); __bss_start = .; 把__bss_start赋值为当前位置,即bss段的开始位置 .bss : { *(.bss) }; 指定bss段 _end = .; 把_end赋值为当前位置,即bss段的结束位置 } |
以上就是u-boot整个工程的链接脚本,它来指定生成的u-boot可执行程序的组成架构。下面列出在u-boot工程编译过程的的最后一步生成u-boot.bin的过程:
arm-linux-ld -Bstatic -T /u-boot-1.3.4/board/mini2440/u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM cpu/arm920t/start.o --start-group lib_generic/libgeneric.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a ……….(省略若干内容) board/mini2440/libmini2440.a --end-group -L /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/armv4t -lgcc -Map u-boot.map -o u-boot
arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
上面可以看到在最后的链接阶段参考了链接脚本的规划,指定了程序的运行地址为0x33f80000,上电启动后,第一阶段的代码就会把u-boot自身搬运到内存的0x33f80000位置去运行。
uboot 链接地址与运行地址的区别的更多相关文章
- ARM裸板开发:04_MMU 链接地址与运行地址不一致时,(SDRAM)初始化程序地址无关码问题的分析
ARM裸板开发过程,程序的链接地址设置为为0x30000000,而前期的启动代码以及相关硬件的初始化代码需要在内部iRAM(steppingstone,起始地址0x0)的4K中运行.链接地址与运行地址 ...
- 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址
驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...
- MAC地址与IP地址的区别
介绍一下MAC地址的知识,MAC地址和IP地址的区别以及MAC地址在实际应用中所涉及到的安全问题. 一.基础知识 如今的网络是分层来实现的,就像是搭积木一样,先设计某个特定功能的模块,然后把模块拼起来 ...
- swift禁用webView对H5中数字,链接,日期,地址,电话号码做解析
showWebView.dataDetectorTypes = .None //swift禁用webView对H5中数字,链接,日期,地址,电话号码做解析 其UIDataDetectorTypes属性 ...
- Uboot 引导内核时加载地址与入口地址问题
如果使用 mkimage 生成内核镜像文件的话,会在内核的前头加上了 64 bytes 的信息头,供建立 tag 之用.bootm 命令会首先判断 bootm xxx 这个指定的地址 xxx 与 -a ...
- uboot生成随机的MAC地址
转载:http://blog.chinaunix.net/uid-25885064-id-3303132.html 在使用U-boot时,有个问题就是MAC地址的设置,如果MAC地址相同的两块开发板在 ...
- load address、entry point、 bootm address以及kernel运行地址
load address:加载地址 load_addr mkimage -a entry point: 入口地址 entry_point mkimage -e bootm ...
- IP地址和物理地址有什么区别
所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址.简单地说就是你在整个互联网上的ID. MAC(Media Access Control,介质访问控制)地址 (物理地址)是 ...
- webpack正式、测试环境接口地址本地运行及打包命令配置
声明:本文由w3h5原创,转载请注明出处:<webpack正式.测试环境接口地址本地运行及打包命令配置> https://www.w3h5.com/post/521.html 为了方便开发 ...
随机推荐
- js 父窗体
1.关闭 父窗体 window.opener.opener=null;window.opener.close() 2.刷新父窗体 JS刷新父窗口的几种方式 浮层内嵌iframe及frame集合窗 ...
- 面试题-链表反转c实现
// ListReverse.cpp : Defines the entry point for the console application.// #include "stdafx.h& ...
- wex5 教程 之 图文讲解 全局可观察变量与登陆状态全局控制
一 先说说,这两个概念是什么意思 全局可观察变量?没听说过,只听过全局变量,那你out了,因为我要充分发挥绑定技术来控制页面部局,组件的隐藏与显示,文字内容,样式改变.看我博文大家知道,我想用绑定技术 ...
- xcode 中 的工程模板
基于视图的应用程序(view-based application) 应用程序如果仅使用一个视图,应该使用这个模板.一个简单的视图控制器会管理应用程序的主视图,而界面布置则使用一个Interface B ...
- selenium处理Ajax浮动框方法
package com.allin.pc;import java.util.List;import org.openqa.selenium.WebElement;import org.openqa.s ...
- 8-JS闭包、回调实例
1.回调 javascipt中,函数回调一般用于以下几种场景: 1.异步执行(例如读取文件,进行HTTP请求) 2.同步(阻塞) 3.事件监听和处理 4.设置超时和时间间隔的方法 异步例子(使用AJA ...
- javascript实现json页面分页
下午有个朋友问json 数据怎么分页 就捣鼓了一个东东出来 下面直接代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...
- 解决 scroll() position:fixed 抖动、导航菜单固定头部(底部)跟随屏幕滚动
一.导航栏或者页脚正常情况下固定在页面的相应位置,当页面滚动后,导航栏或者页脚固定在页面的顶部或者底部的情景 一般就是将该块的代码样式的position设置为fixed.固定在顶部的话,将top设置为 ...
- JavaScript学习笔记及知识点整理_1
一.js的基础部分 1.==和===的区别:==在判断是否相等的时候会进行类型转换,有时会得到非常奇怪的结果,因此一般情况下都是用===判断是否相等2.strict模式:在js中,如果一个变量没有用v ...
- 【转】Vim十大必备插件
[转]Vim十大必备插件 转自:http://my.oschina.net/zhoukuo/blog/336315 Taglist taglist是一个用于显示定位程序中各种符号的插件,例如宏定义.变 ...