历史上的今天
返回首页

历史上的今天

今天是:2024年09月10日(星期二)

正在发生

2021年09月10日 | S3c2440代码重定位详解5---代码重定位与位置无关码

2021-09-10 来源:eefocus

一个程序,由代码段、只读数据段、数据段、bss段等组成。


程序一开始可以烧在Nor Flash上面,运行时代码段仍可以在Nor Flash运行,但对于数据段,就必须把数据段移到SDRAM中,因为只要在SDRAM里面,数据段的变量才能被写操作,把程序从一个位置移动到另一个位置,把这个过程就称为重定位。


先梳理下把整个程序复制到SDRAM需要哪些技术细节:


把程序从Flash复制到运行地址,链接脚本中就要指定运行地址(Runtime addr)为SDRAM地址;

编译链接生成的bin文件,需要在SDRAM地址上运行,但上电后却必须先在0地址运行,这就要求重定位之前的代码与位置无关(是位置无关码写成);

参考Uboot修改链接脚本:

SECTIONS

{

    . = 0x30000000;


    . = ALIGN(4);

    .text      :

    {

      *(.text)

    }


    . = ALIGN(4);

    .rodata : { *(.rodata) }


    . = ALIGN(4);

    .data : { *(.data) }


    . = ALIGN(4);

    __bss_start = .;

    .bss : { *(.bss) *(.COMMON) }

    _end = .;

}


现在我们写的这个链接脚本,称为一体式链接脚本,对比前面的分体式链接脚本区别在于代码段和数据段的存放位置是否是分开的。


例如现在的一体式链接脚本的代码段后面依次就是只读数据段、数据段、bss段,都是连续在一起的。


分体式链接脚本则是代码段、只读数据段,中间相关很远之后才是数据段、bss段。

我们以后的代码更多的采用一体式链接脚本,原因如下:


分体式链接脚本适合单片机,单片机自带有flash,不需要再将代码复制到内存占用空间。而我们的嵌入式系统内存非常大,没必要节省这点空间,并且有些嵌入式系统没有Nor Flash等可以直接运行代码的Flash,就需要从Nand Flash或者SD卡复制整个代码到内存;

JTAG等调试器一般只支持一体式链接脚本;

修改start.S段


    /* 重定位text, rodata, data段整个程序 */

    mov r1, #0

    ldr r2, =_start         /* 第1条指令运行时的地址 */

    ldr r3, =__bss_start    /* bss段的起始地址 */


cpy:

    ldr r4, [r1]

    str r4, [r2]

    add r1, r1, #4

    add r2, r2, #4

    cmp r2, r3

    ble cpy



    /* 清除BSS段 */

    ldr r1, =__bss_start

    ldr r2, =_end

    mov r3, #0

clean:

    str r3, [r1]

    add r1, r1, #4

    cmp r1, r2

    ble clean


    bl main  


halt:

    b halt


将修改后的代码重新编译烧写在Nor Flash上,上电运行。

对本代码的启动情况进行分析:

在这里插入图片描述

在生成的bin文件里,代码保存的位置是0x30000000。随后烧写到NOR Flash的0地址,但代码的结构没有变化。之后再重定位到SDRAM


查看反汇编:


3000005c:   eb000106    bl  30000478  


30000060:   e3a01000    mov r1, #0  ; 0x0

30000064:   e59f204c    ldr r2, [pc, #76]   ; 300000b8 <.text+0xb8>

30000068:   e59f304c    ldr r3, [pc, #76]   ; 300000bc <.text+0xbc>


这里的bl 30000478不是跳转到30000478,这个时候sdram并未初始化;

为了验证,我们做另一个实验,修改连接脚本sdram.lds, 链接地址改为0x32000478,编译,查看反汇编:


3000005c:   eb000106    bl  30000478  


30000060:   e3a01000    mov r1, #0  ; 0x0

30000064:   e59f204c    ldr r2, [pc, #76]   ; 300000b8 <.text+0xb8>

30000068:   e59f304c    ldr r3, [pc, #76]   ; 300000bc <.text+0xbc>


可以看到现在变成了bl 30000478,但两个的机器码eb000106都是一样的,机器码一样,执行的内容肯定都是一样的。

因此这里并不是跳转到显示的地址,而是跳转到: pc + offset,这个由链接器决定。


假设程序从0x30000000执行,当前指令地址:0x3000005c ,那么就是跳到0x30000478;如果程序从0运行,当前指令地址:0x5c 调到:0x00000478


跳转到某个地址并不是由bl指令所决定,而是由当前pc值决定。反汇编显示这个值只是为了方便读代码。


重点:

反汇编文件里, B或BL 某个值,只是起到方便查看的作用,并不是真的跳转。


怎么写位置无关码?


1、使用相对跳转命令 b或bl;

2、重定位之前,不可使用绝对地址,不可访问全局变量/静态变量,也不可访问有初始值的数组(因为初始值放在rodata里,使用绝对地址来访问);

3、重定位之后,使用ldr pc = xxx,跳转到/runtime地址;


写位置无关码,其实就是不使用绝对地址,判断有没有使用绝对地址,除了前面的几个规则,最根本的办法看反汇编。


因此,前面的例子程序使用bl命令相对跳转,程序仍在NOR/sram执行,要想让main函数在SDRAM执行,需要修改代码


 //bl main  /*bl相对跳转,程序仍在NOR/sram执行*/

 ldr pc, =main/*绝对跳转,跳到SDRAM*/

推荐阅读

史海拾趣

CYMBET公司的发展小趣事

随着EnerChip技术的不断完善和市场的认可,CYMBET公司开始积极拓展市场,与全球各地的合作伙伴建立了紧密的合作关系。例如,CYMBET与Digi-Key Corporation签订了全球经销协议,通过Digi-Key的广泛分销网络,EnerChip系列固态可充电薄膜电池及能量采集储能模块得以迅速进入全球市场。此外,CYMBET还与多家知名电子设备制造商建立了长期合作关系,共同开发新产品,推动电子行业的发展。

灿科盟(Ckmtw)公司的发展小趣事

灿科盟电子实业有限公司成立于2003年8月,注册资金100万。公司创始人凭借在电子行业多年的积累,决定创立自有品牌“CKMTW”,专注于连接器产品的研发与生产。在初创阶段,公司面临着资金紧张、市场竞争激烈等挑战,但凭借坚定的信念和不断的技术创新,逐渐在市场中站稳脚跟。

High Voltage Power Solutions Inc公司的发展小趣事

灿科盟电子实业有限公司成立于2003年8月,注册资金100万。公司创始人凭借在电子行业多年的积累,决定创立自有品牌“CKMTW”,专注于连接器产品的研发与生产。在初创阶段,公司面临着资金紧张、市场竞争激烈等挑战,但凭借坚定的信念和不断的技术创新,逐渐在市场中站稳脚跟。

CalRamic Technologies Llc公司的发展小趣事

为了保证产品质量的稳定性和可靠性,CalRamic Technologies在公司成立不久后,就开始着手建立严格的质量管理体系。他们引入了国际先进的质量管理理念和方法,对每一个生产环节进行严格把控。这一举措大大提高了产品的合格率和客户满意度,为公司的长期发展奠定了坚实基础。

CINTERION公司的发展小趣事

2010年,电子支付与身份识别技术领域的领军企业金雅拓,全资收购了CINTERION。这一资本动作不仅为CINTERION带来了更多的资金支持,更使其在金雅拓的物联网事业部中获得了更广阔的发展空间。收购完成后,CINTERION继续保持其技术领先地位,并在金雅拓的推动下,进一步拓宽了产品线和应用领域。

Dresden Elektronik公司的发展小趣事

随着技术的不断进步,Dresden Elektronik公司不断加大对研发的投入,致力于推动技术的创新和突破。一次偶然的实验中,公司的研发团队发现了一种新的材料,能够显著提高电子元件的性能和稳定性。这一发现被迅速转化为产品,并成功推向市场,使公司的产品在竞争中脱颖而出。

问答坊 | AI 解惑

mifare卡读写器开发心得『转』

坛子里好像越来越多的人对此产生了兴趣。我最初的读卡器是用CM200开发的,硬件开发没有什么特别的,CM200内部带地址锁存,接口很方便,其它的按照datasheet照搬就行了。关键是天线板的设计,尺寸形状都会影响,而我觉得这些定了之后,设计的关键又 ...…

查看全部问答>

通过mini2440的蜂鸣器演奏“两只老虎”

程序模拟了音乐的七个音皆(do,re,me,fa,so,la,si),包括低音,中音及高音. 有兴趣的朋友可下载程序到target board一试,或到以下网站观看示范片段. http://v.youku.com/v_show/id_XMTQwMjI0MjI0.html 附件是作者提供的Qtopia应用程序,感兴趣的 ...…

查看全部问答>

一位值得借鉴的电子专业学长的足迹

本帖最后由 paulhyde 于 2014-9-15 09:30 编辑 在哈尔滨工程大学六年,我在学校电子创新实验室呆了四年,这四年里创新实验室给我提供了良好的学习环境和完善的实验设备;在与众多电子爱好者的交流中,使我学到了更多的专业知识;在学校老师们的教 ...…

查看全部问答>

Windows CE系统中卫星通信的实现.pdf

Windows CE系统中卫星通信的实现.pdf…

查看全部问答>

wince找师傅带我入门

初学wince,指望高手指点下明路,要具体点的。不要什么一句话去看书。没用的,我只要快点入门。…

查看全部问答>

请问如何设计一个类似BTS功能的设备,可以取得无线L3的消息?

  请问如何从空口中提取L3的信号,应该使用何种模块??   TC35系列芯片虽然可以处理GSM协议栈,但不知道是否可以从其端口取得空口的的消息?   现有如下思路如下:      天线 + ??1 + TC ...…

查看全部问答>

如何烧写u-boot和uClinux?

我在linux系统下编译u-boot生成u-boot、u-boot.bin和u-boot.srec三个文件,编译uClinux(2.4.x版)后生成image.ram、image.rom 和 romfs.img。请问用什么工具烧写u-boot和uClinux呢?应该烧哪些文件呢?有没有相关的文档?我之前移植ucos等都是用H- ...…

查看全部问答>

两个小问题,散分了~

1. 用硬件定时器编写程序,设置时、分、秒定时器,分别对应的地址为:4000H、4002H、4004H,晶振频率为12MHZ(用8096编写) 2.C08__2  MODULE MAIN     $INCLUDE(8096.INT) PORT   EQU   OFFA8H  ...…

查看全部问答>

请高手指点---请教并口EPP模式通信的问题

我用电脑并口与51单片机通信的时候,采取的是EPP1.9模式,发现老是nWait=1,不知道什么原因, 有没有这方面的前辈指导一下。感谢不尽。 源码如下: #include /* inp, outp */ #include   /* kbhit() et al  */ #incl ...…

查看全部问答>

51 to ARM

从8位机到32位机过渡的捷径…

查看全部问答>