重定位——重定位的简介与操作(涉及位置无关码)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

参考博客:位置无关码、位置有关码 - biaohc - 博客园

一、链接地址与运行地址

1、链接地址

链接地址,是指程序员通过Makefile中“ -Ttext  xxx ”或者在链接脚本中指定的地址。程序员预先知道程序的执行要求,比如放在哪里才能顺利执行,于是就把这个地址当做链接地址。

(1)Linux中应用程序默认的链接地址是0x0000_0000

Linux中应用程序默认链接地址是0x0000_0000,比如使用命令“gcc hello.c -o hello”进行编译与链接时,使用的就是默认的链接地址0x0000_0000。

每个应用程序运行在一个独立进程中,可以独享4G的虚拟地址空间,因此每个应用程序都可以链接到0x0000_0000地址处,因为每个进程都是从0地址开始的。

(2)X210中裸机程序的链接地址应该为0xd002_0010

X210开发板的链接地址,理论上应该是0xd002_0010。这个地址不是随意定的,而是iROM中的BL0加载BL1时指定好的地址,由CPU设计时决定的。

2、运行地址

运行地址,是指代码运行时的地址。

运行时地址无法在编译链接时绝对地确定,它是在下载时确定的。

二、重定位与位置无关码

1、重定位的概念

链接地址和运行地址可能不同,比如我们指定链接地址为0xd0024000,但后来通过dnw软件将镜像文件下载到0xd002_0010,则此时的运行地址是0xd002 0010。

这种情况下,如果镜像文件里有位置相关码,则位置相关码会运行不起来,因为位置已经发生改变。因此在位置相关码运行之前,需要先执行一段位置无关码,把整个镜像文件拷贝到以链接地址为起始地址的空间里,然后通过长跳转指令,跳转到(以链接地址为起始地址的那份代码的)相应位置继续运行。

当执行完代码重定位后,在SRAM中有2份镜像文件,一份是下载到0xd0020010处开头的镜像文件,另一份是复制到0xd0024000处开头的镜像文件。

接下来如果使用短跳转bl led_blink,则执行的是运行地址0xd0020010开头的那一份代码。如果使用长跳转ldr pc, =led_blink,则执行的是链接地址 0xd0024000 开头的那一份代码,即直接从 0xd0020010开头的代码跳转到0xd0024000开头的那一份代码的 led_blink函数处。当链接地址和运行地址相同时,短跳转和长跳转效果是一样的。

注意

(1)adr指令加载符号地址,加载的是运行时地址;ldr指令在加载符号地址时(第1个操作数是pc则叫长跳转,若是其他寄存器则叫长加载),加载的是链接地址。

(2)长跳转指的是跳转到的地址和当前地址差异比较大,跳转的范围比较宽广。它通过给PC(r15)赋一个新值来完成代码段的跳转执行。

2、位置无关码的概念

位置无关码与位置有关码的实质区别,在于操作时,位置有关码使用的是绝对地址,而位置无关码使用的是相对地址(PC + offset),主要体现在取址、跳转这两个操作上。判断方法就是看某指令是否受到链接脚本中链接地址的影响。

常见的情形分析

(1)b、BL指令用的都是相对地址,所以是位置无关码。

(2)ldr pc,=main;因为main标志在编译的时候,会受到链接脚本的链接位置的影响,因此main是链接后的绝对地址,所以是位置有关码。

(3)ldr r0, =bss_start,这句代码的作用是把bss_start(在链接脚本中)的地址放入r0中,因为bss_start的值会受到链接脚本中链接位置的影响,因此bss_start是链接后的绝对地址,所以是位置有关码。

(4)ldr r0, 0xe0002700;这个操作取0xe0002700内存地址中的值赋值给r0,因为这个内存地址不会受到链接脚本中链接位置的影响,所以是位置无关码。下面的这几句代码也不会受到链接脚本中链接地址的影响,所以也是位置无关码。

#define WTCON         0xE2700000
#define PS_HOLD_CONTROL  0xE010E81C
#define SVC_STACK      0xD0037D80
ldr r0, =WTCON
ldr r0, =PS_HOLD_CONTROL

三、例子说明

1、在SRAM内部重定位

/** 文件名:	led.s	* 描述:	演示重定位(在SRAM内部重定位,不涉及内存的初始化)*/#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start					// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]// 第2步:设置SVC栈ldr sp, =SVC_STACK// 第3步:开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;// 第4步:重定位// adr指令用于加载_start当前运行地址adr r0, _start  		// adr加载时就叫短加载		// ldr指令用于加载_start的链接地址:0xd0024000ldr r1, =_start // ldr加载时如果目标寄存器是pc就叫长跳转,如果目标寄存器是r1等就叫长加载	// bss段的起始地址ldr r2, =bss_start	// 就是我们重定位代码的结束地址,重定位只需重定位代码段和数据段即可cmp r0, r1			// 比较_start的运行时地址和链接地址是否相等beq clean_bss		// 如果相等说明不需要重定位,所以跳过copy_loop,直接到clean_bss// 如果不相等说明需要重定位,那么直接执行下面的copy_loop进行重定位// 重定位完成后继续执行clean_bss。// 用汇编来实现的一个while循环
copy_loop:ldr r3, [r0], #4    // 源str r3, [r1], #4	// 目的   这两句代码就完成了4个字节内容的拷贝cmp r1, r2			// r1和r2都是用ldr加载的,都是链接地址,所以r1不断+4总能等于r2bne copy_loop// 清bss段,其实就是在链接地址处把bss段全部清零
clean_bss:ldr r0, =bss_start					ldr r1, =bss_endcmp r0, r1				// 如果r0等于r1,说明bss段为空,直接下去beq run_on_dram			// 清除bss完之后的地址mov r2, #0
clear_loop:str r2, [r0], #4		// 先将r2中的值放入r0所指向的内存地址(r0中的值作为内存地址),cmp r0, r1				// 然后r0 = r0 + 4 即地址加4bne clear_looprun_on_dram:	// 长跳转到led_blink开始第二阶段ldr pc, =led_blink				// ldr指令实现长跳转// 从这里之后就可以开始调用C程序了//bl led_blink					// bl指令实现短跳转// 汇编最后的这个死循环不能丢b .

清除bss段是为了满足C语言的运行时要求(C语言要求显式初始化为0的全局变量,或者未显式初始化的全局变量的值为0,实际上C语言编译器就是通过清bss段来实现C语言的这个特性的)。一般情况下我们的程序是不需要负责清零bss段的(C语言编译器和链接器会帮我们的程序自动添加一段头程序,这段程序会在我们的main函数之前运行,这段代码就负责清除bss)。但是在我们代码重定位了之后,因为编译器帮我们附加的代码只是帮我们清除了运行地址那一份代码中的bss,而未清除重定位地址处开头的那一份代码的bss,所以重定位之后需要自己去清除bss。

2、重定位到内存中

/** 文件名:	led.s	* 描述:	演示重定位至DDR中,,需要先初始化内存*/#define WTCON		0xE2700000#define SVC_STACK	0xd0037d80.global _start					// 把_start链接属性改为外部,这样其他文件就可以看见_start了
_start:// 第1步:关看门狗(向WTCON的bit5写入0即可)ldr r0, =WTCONldr r1, =0x0str r1, [r0]// 第2步:设置SVC栈ldr sp, =SVC_STACK// 第3步:开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;// 第4步:初始化ddrbl sdram_asm_init// 第5步:重定位// adr指令用于加载_start当前运行地址adr r0, _start  		// adr加载时就叫短加载		// ldr指令用于加载_start的链接地址:0xd0024000ldr r1, =_start // ldr加载时如果目标寄存器是pc就叫长跳转,如果目标寄存器是r1等就叫长加载	// bss段的起始地址ldr r2, =bss_start	// 就是我们重定位代码的结束地址,重定位只需重定位代码段和数据段即可cmp r0, r1			// 比较_start的运行时地址和链接地址是否相等beq clean_bss		// 如果相等说明不需要重定位,所以跳过copy_loop,直接到clean_bss// 如果不相等说明需要重定位,那么直接执行下面的copy_loop进行重定位// 重定位完成后继续执行clean_bss。// 用汇编来实现的一个while循环
copy_loop:ldr r3, [r0], #4    // 源str r3, [r1], #4	// 目的   这两句代码就完成了4个字节内容的拷贝cmp r1, r2			// r1和r2都是用ldr加载的,都是链接地址,所以r1不断+4总能等于r2bne copy_loop// 清bss段,其实就是在链接地址处把bss段全部清零
clean_bss:ldr r0, =bss_start					ldr r1, =bss_endcmp r0, r1				// 如果r0等于r1,说明bss段为空,直接下去beq run_on_dram			// 清除bss完之后的地址mov r2, #0
clear_loop:str r2, [r0], #4		// 先将r2中的值放入r0所指向的内存地址(r0中的值作为内存地址),cmp r0, r1				// 然后r0 = r0 + 4bne clear_looprun_on_dram:	// 长跳转到led_blink开始第二阶段ldr pc, =led_blink				// ldr指令实现长跳转// 从这里之后就可以开始调用C程序了//bl led_blink					// bl指令实现短跳转// 汇编最后的这个死循环不能丢b .

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV学习(27) 直方图(4)

我们可以利用OpenCV的直方图&#xff0c;backproject直方图和meanshift算法来跟踪物体。下面通过简单的例子来说明如何实现跟踪算法&#xff0c;我们有两幅狒狒的图片&#xff0c;如下图所示&#xff1a;我们首先在左图中框选狒狒的脸&#xff0c;计算出框选区域的色度(HSV空间…

MySQL源码编译与初始化

MySQL源码编译与初始化 链接&#xff1a;https://pan.baidu.com/s/1ANGg3Kd_28BzQrA5ya17fQ 提取码&#xff1a;ekpy 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 1.MySQL简介 1.1数据库有很多种类&#xff1a; 关系型数据库--->MySQL Oracle非关系型数据库…

uboot中的虚拟地址映射

1、DRAM有效范围 &#xff08;1&#xff09;DMC0上允许的地址范围是20000000-3FFFFFFF&#xff08;一共是512MB&#xff09;&#xff0c;而X210开发板实际只接了256MB物理内存&#xff0c;SoC允许我们给这256MB挑选地址范围。在裸机中DMC0的地址范围是0x20000000-0x2FFFFFFF&am…

.net remoting 技术

Remoting编辑目 录 1简介 2主要元素 3两种通道 4激活方式 5对象定义 6服务器 7客户 8基础补充 9小结 1简介 什么是Remoting&#xff0c;简而言之&#xff0c;我们可以将其看作是一种分布式处理方式 。从微软的产品角度来看&#xff0c;可以说Remoting就是DCOM的一种升级&#x…

浪客剑心:位图法Bitmap算法分析

看了博客园里一篇文章《一道腾讯前端试题&#xff0c;谁来试试身手》&#xff0c;正好以前了解过位图法&#xff0c;确实不错。位图法适用于大规模数据&#xff0c;但数据状态又不是很多的情况。通常是用来判断某个数据存不存在&#xff0c;如可标记1为存在&#xff0c;0为不存…

GoogLeNet结构

Inception V1 GoogLeNet结构&#xff08;Inception V1&#xff09; 输入为224x224的RGB图像&#xff0c;‘#3x3 reduce’和‘#5x5 reduce’表示3x3和5x5卷积之前1x1的卷积核的个数。 转载于:https://www.cnblogs.com/Peyton-Li/p/11201038.html

uboot的移植——移植三星官方的uboot到x210开发板

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、移植总结 二、移植过程 1、获取三星官方版本的uboot &#xff08;1&#xff09;由于X210开发板使用S5PV210这款CPU&#xff0c;因此我们应该寻找一块使用相同CPU的开发板&#xff0c;然后以这块…

Hadoop 文件命令

为什么80%的码农都做不了架构师&#xff1f;>>> * 文件操作 * 查看目录文件 * $ hadoop dfs -ls /user/cl * * 创建文件目录 * $ hadoop dfs -mkdir /user/cl/temp * * 删除文件 * $ hadoop dfs -rm /user/cl/temp/a.txt * * 删除目录与目录下所有文件 …

Swans and ducks, Piešťany, Slovakia

What Makes This a Photo of the Day? I love the slightly off-kilter composition here, with the cluster of birds near the bottom of the frame. This gives a sense of movement and allows the eye to take in the peripheral elements—the ripples of the water and…

python day15

今日内容 昨日内容补充: 对于两个文件中的互相导入md模块问题分析: x 1from md import xprint(x)# md中的xfrom md import xx 1000print(x)# 当前文件中的x __all__ 列表写什么,执行导入语句那个文件就能拿到什么; __all__不写的情况,默认是将所在文件所有的名字都暴露给导入…

如何有效抓取SQL Server的BLOCKING信息

2019独角兽企业重金招聘Python工程师标准>>> SQL Server允许并发操作&#xff0c;BLOCKING是指在某一操作没有完成之前&#xff0c;其他操作必须等待&#xff0c;以便于保证数据的完整性。BLOCKING的解决方法要查看BLOCKING的头是什么&#xff0c;为什么BLOCKING头上…

iOS开发篇——OC 协议和代理设计模式介绍

蓝鸥iOS培训讲师推荐&#xff1a;好久没和大家沟通了&#xff0c;没和大家沟通了&#xff0c;今天就和大家说说有关OC内容协议和代理设计模式。首先要讲的是协议一、协议OC中的协议和接口有些相似&#xff0c;协议中定义的方法&#xff0c;在类中实现。协议一般情况下是用来实现…

uboot的移植——移植uboot官方的uboot到x210开发板

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考内容 uboot——官网下载直接移植(一) - biaohc - 博客园 uboot——官网下载直接移植(二) - biaohc - 博客园 uboot移植&#xff08;一&#xff09;配置过程分析_LouisGou的博客-CSDN博客 获取…

[转载]使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)...

前言 本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术&#xff0c;还需思考产品的设计&#xff0c;如何将新加的功能更好的融入到现有的产品中&#xff0c;并不是简单的加一个界面就行了&#xff0c;欢迎大家交流产品设计和技术细节实现&#xff01…

Hibernate上路_16-继承关系映射

2019独角兽企业重金招聘Python工程师标准>>> 例&#xff1a;员工Employee分为正式工SalaryEmployee和临时工HourEmployee。子类表的字段都不能使用非空约束。 1.三种继承关系的建表方式&#xff1a; 1&#xff09;父类、子类在同一张表&#xff0c;表中有“辨别者…

C++起航篇——bool类型,输入输出,命名空间

以下内容源于慕课网http://www.imooc.com/course/list?ccplusplus的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 慕课网学习内容 一、起航 二、离航 三、远征 封装继承多态模板 1、c的新特征 &#xff08;1&#xff09;新数据类型 bool &#xff08;true和fals…

C++离航篇——引用,const

以下内容源于http://www.imooc.com/learn/381的学习整理&#xff0c;如有侵权&#xff0c;请告知删除。 一、引用 &#xff08;1&#xff09;引用即定义别名 对引用进行操作即对本身操作&#xff1b;int a10; int &ba; //定义了a的别名b&#xff1b;注意别名是不包括&…

【广搜】棋盘游戏

题目描述 在一个4*4的棋盘上有8个黑棋和8个白棋&#xff0c;当且仅当两个格子有公共边&#xff0c;这两个格子上的棋是相邻的。移动棋子的规则是交换相邻两个棋子。现在给出一个初始棋盘和一个最终棋盘&#xff0c;要求你找出一个最短的移动序列使初始棋盘变为最终棋盘。Klux说…

C++离航篇——函数默认参数、函数重载、内敛函数

1、函数的默认参数 2、函数的重载 &#xff08;1&#xff09;在相同的作用域内&#xff0c;用同一个函数名定义的多个函数&#xff0c;其中每个函数的参数个数、参数类型不同。 3、内联函数 &#xff08;1&#xff09;编译的时候&#xff0c;将函数体代码和相应的实参直接在函…