1.代码重定位的改进

  1. 用ldr、str代替ldrb, strb加快代码重定位的速度

    前面重定位时,我们使用的是ldrb命令从的Nor Flash读取1字节数据,再用strb命令将1字节数据写到SDRAM里面。

    我们2440开发板的Nor Flash是16位,SDRAM是32位。 假设现在需要复制16byte数据。

    不同的读写指令 cpu读取nor的次数 cpu写入sdram的次数
    ldrb、strb 16 16
    ldr、str 8 4

    可以看出我们更换读写指令后读写次数变少了,提升了cpu的访问效率。

    修改后的start.s代码如下图所示,这里我只简单的列出了重定位的实现:

     ...
    cpy:
    ldr r4, [r1]
    str r4, [r2]
    add r1, r1, #4 //r1加4
    add r2, r2, #4 //r2加4
    cmp r2, r3 //如果r2 =< r3继续拷贝
    ble cpy
    ...
  2. 用c语言实现重定位

添加如下链接脚本:

SECTIONS
{
. = 0x30000000; __code_start = .; . = ALIGN(4);
.text :
{
*(.text)
} . = ALIGN(4);
.rodata : { *(.rodata) } . = ALIGN(4);
.data : { *(.data) } . = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) *(.COMMON) }
_end = .;
}

在main.c中添加如下函数实现:

void copy2sdram(void)
{
//要从lds文件中获得 __code_start, __bss_start
//然后从0地址把数据复制到__code_start extern int __code_start, __bss_start; volatile unsigned int *dest = (volatile unsigned int *)&__code_start;
volatile unsigned int *end = (volatile unsigned int *)&__bss_start;
volatile unsigned int *src = (volatile unsigned int *)0; while (dest < end)
{
*dest++ = *src++; //从0地址依次copy到__code_start(代码段的运行地址)
}
}

然后在start.s中设置栈指针sp后,即可执行bl copy2sdram进行重定位代码。如何设置栈指针请参考

时钟编程(二、配置时钟寄存器)中有实现,重复代码我就不贴上来了。

2.清bss的改进

  1. 用ldr、str代替ldrb, strb加快清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
  2. c语言实现清bss

    和上面重定位的代码实现一样,就是往bss段全部写0. 执行完bl copy2sdram, 然后再bl clean_bss即可完成清除bss段。

     void clean_bss(void)
    {
    /* 从lds文件中获得 __bss_start, _end*/
    extern int _end, __bss_start; volatile unsigned int *start = (volatile unsigned int *)&__bss_start;
    volatile unsigned int *end = (volatile unsigned int *)&_end; while (start <= end)
    {
    *start++ = 0;
    }
    }

    注意:汇编代码获取的是链接脚本中的变量的地址,而C语言代码中获取的是链接脚本中的变量的值,所以这里的用C语言改进重定位还是清bss都是要加取址符。

  3. 保证所有段的起始地址以4字节对齐

    我们前面为了加快重定位和清bss的速度,用到了ldr,str这样以4字节为单位进行读写,但是还可能导致一个问题,假设现在链接脚本没有进行用ALIGN(4)让不同的段以4字节对齐,那么就会出现访问错乱的情况。

    我举个例子:

     #include "s3c2440_soc.h"
    #include "uart.h"
    #include "init.h" char g_Char = 'A'; //.data
    char g_Char3 = 'a';
    const char g_Char2 = 'B'; //.rodata
    int g_A = 0; //bss
    int g_B; //bss int main(void)
    {
    uart0_init(); puts("\n\rg_A = ");
    printHex(g_A);
    puts("\n\r");
    putchar(g_Char);
    return 0;
    }

    将链接脚本中.data段和.bss之间的ALIGN(4)去掉。那么我们会发现程序执行的时候输出的g_A=0,为什么呢,我们明明初始化g_A=‘A’呀?

    我们分析下反汇编看看:

    我们的.bss段紧接着.data段后面,可知在对bss段进行清除的时候,由于我们是以4字节为单位操作的,所以我们清除g_A的时候,连带g_Char,g_Char的值也一起清除了。所以data段和数据段之间添加ALIGN(4)。修改后就会发现bss段的地址以0x30000248开始了,如下图:

3.位置无关码

我们对‘bl sdram_init’指令进行分析:

查看反汇编:(代码段的链接地址为0x3000,0000)

这里的bl 3000036c不是跳转到3000036c,这个时候sdram并未初始化,那么这个物理地址是无法访问的;

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

可以看到现在变成了bl 300003ec,但两个的机器码e1a0c00d都是一样的,机器码一样,执行的内容肯定都是一样的。 因此这里并不是跳转到显示的地址,而是跳转到: pc + offset,这个由链接器决定。

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

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

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

怎么写位置无关码?

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

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

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

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

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

  //bl main  /*bl相对跳转,程序仍在NOR/sram执行*/
ldr pc, =main/*绝对跳转,跳到SDRAM*/

s3c2440裸机-代码重定位、清bss的改进和位置无关码的更多相关文章

  1. s3c2440裸机-代码重定位(1.重定位的引入,为什么要代码重定位)

    1.重定位的引入(为什么要代码重定位) 我们知道s3c2440的cpu从0地址开始取指令执行,当从nor启动时,0地址对应nor,nor可以像内存一样读,但不能像内存一样写.我们能够从nor上取指令执 ...

  2. s3c2440裸机-代码重定位(2.编程实现代码重定位)

    代码重定位(2.编程实现代码重定位) 1.引入链接脚本 我们上一节讲述了为什么要重定位代码,那么怎么去重定位代码呢? 上一节我们发现"arm-linux-ld -Ttext 0 -Tdata ...

  3. S3C2440—10.代码重定位

    文章目录 一.启动方式 1.1 NAND FLASH 启动 1.2 NOR FLASH 启动 二. 段的概念 2.1 重定位数据段 2.2 加载地址的引出 三.链接脚本 3.1 链接脚本的引入 3.2 ...

  4. uboot 与 代码重定位

    ref: https://blog.csdn.net/dhauwd/article/details/78566668 https://blog.csdn.net/yueqian_scut/articl ...

  5. 代码重定位和位置无关码——运行于nor flash

    通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简 ...

  6. s3c6410_uboot中的代码重定位(nand->sdram)

    本文仅探讨s3c6410从nand flash启动u-boot时的代码重定位过程 参考: 1)<USER'S MANUAL-S3C6410X>第二章 MEMORY MAP 第八章 NAND ...

  7. linux上使用J-Link调试S3C2440裸机代码

    linux上使用J-Link调试S3C2440裸机代码 工具: segger的jlink仿真器 segger的jlink for linux 交叉编译工具链里面的arm-xx-linux-xx-gdb ...

  8. Linux从头学06:16张结构图,彻底理解【代码重定位】的底层原理

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

  9. s3c2440代码重定位和段的引入——学以致用,综合Makefile的锻炼

    对于2440而言,nand启动,nand的前4k内容由硬件复制到sram. nor flash,可以像内存一样读,但是不能像内存一样写,执行写操作需要特殊的操作. 程序中包含有需要写的全局或者静态变量 ...

随机推荐

  1. CoderForces-Round60D(1117) Magic Gems

    D. Magic Gems time limit per test 3 seconds memory limit per test 256 megabytes input standard input ...

  2. Vue - watch高阶用法

    1. 不依赖新旧值的watch 很多时候,我们监听一个属性,不会使用到改变前后的值,只是为了执行一些方法,这时可以使用字符串代替 data:{ name:'Joe' }, watch:{ name:' ...

  3. iSensor APP 之 摄像头调试 OV9655 测试之二

    参考上一篇博客 iSensor APP 之 摄像头调试 OV9655 本次链接主要介绍,使用ov9655输出QVGA格式,320*240  YUV输出,图像效果还不错,用户可以参考此模板改变分辨率,不 ...

  4. 解决:Sass Loader has been initialised using an options object that does not ma tch the API schema.

    今天是犯傻的一天,第一回用sass遇到了bug: 结果就是:<style lang = 'scss'>.写成了<style lang = 'sass'> (脑子要清醒一点.太笨 ...

  5. 201871010119-帖佼佼《面向对象程序设计(java)》第十四周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...

  6. 12个超好用的IntelliJ IDEA 插件!你用过几个?

    一.前言 IntelliJ IDEA 如果说IntelliJ IDEA是一款现代化智能开发工具的话,Eclipse则称得上是石器时代的东西了. 其实笔者也是一枚从Eclipse转IDEA的探索者,随着 ...

  7. 还不懂MySQL索引?这1次彻底搞懂B+树和B-树

    前言 看了很多关于索引的博客,讲的大同小异.但是始终没有让我明白关于索引的一些概念,如B-Tree索引,Hash索引,唯一索引….或许有很多人和我一样,没搞清楚概念就开始研究B-Tree,B+Tree ...

  8. 搭建react native所遇到的坑

    一.所遇问题 在搭建react native环境中,遇到执行react native  run-android命令出现如下问题 Could not resolve all dependencies f ...

  9. hexo + next 搭建博客时Cannot GET /tags/问题处理

    原来是要修改新建的index.md文件,不仔细. 此外,愈发觉得百度和谷歌搜索同一问题的差距,谷歌更适合程序员! https://www.zhihu.com/question/29017171 这个可 ...

  10. 萌新入门Github请看这里,学不会远程教

    一些废话 本文的主旨是为初次接触Github的同学提供一个入门的教程,如果你已经是Github老鸟,可以忽略本文哦,另外本文只是抛砖引玉,其实最好的教程是官方文档!!! Github官网 Github ...