历史上的今天
返回首页

历史上的今天

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

正在发生

2021年09月10日 | S3c2440代码重定位详解6---重定位清除BSS段的C函数实现

2021-09-10 来源:eefocus

在前面,我们使用汇编程序来实现了重定位和清bss段,本节我们将使用C语言,实现重定位和清除bss段。


1.打开start.S把原来的汇编代码删除改为调用C函数


    /* 重定位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


改为:


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

    mov r0, #0

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

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

    sub r2, r2, r1          /*长度*/



    bl copy2sdram  /* src, dest, len */


    /* 清除BSS段 */

    ldr r0, =__bss_start

    ldr r1, =_end


    bl clean_bss  /* start, end */


1、在init.c 实现如上两个C函数


void copy2sdram(volatile unsigned int *src, volatile unsigned int *dest, unsigned int len)  /* src, dest, len */

{

    unsigned int i = 0;


    while (i < len)

    {

        *dest++ = *src++;

        i += 4;

    }

}



void clean_bss(volatile unsigned int *start, volatile unsigned int *end)  /* start, end */

{

    while (start <= end)

    {

        *start++ = 0;

    }

}


汇编中,为C语言传入的参数,依次就是R1、R2、R3。

编译,烧写运行没有问题。


我们假设不想汇编传入参数,而是C语言直接取参数。

1、修改start.S 跳转到C函数不需要任何参数


    bl sdram_init

    //bl sdram_init2     /* 用到有初始值的数组, 不是位置无关码 */


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

    bl copy2sdram


    /* 清除BSS段 */

    bl clean_bss


2、修改链接脚本,让__code_start 等于当前地址,也就是这里的0x30000000


SECTIONS

{

    . = 0x30000000;


    __code_start = .; //定义__code_start地址位当前地址


    . = ALIGN(4);

    .text      :

    {

      *(.text)

    }


    . = ALIGN(4);

    .rodata : { *(.rodata) }


    . = ALIGN(4);

    .data : { *(.data) }


    . = ALIGN(4);

    __bss_start = .;

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

    _end = .;

}


3、修改init.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++;

    }

}



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函数怎么使用lds文件总的变量abc?

1、在C函数中声明改变量为extern外部变量类型,比如extern int abc;

2、使用时,要取址,比如:int *p = &abc;//p的只即为lds文件中abc的值

汇编文件中可以直接使用外部链接脚本中的变量,但C函数中要加上取址符号。


解释一下原因:

C函数中,定义一个全局变量int g_i;程序中必然有4字节的空间留出来给这个变量g_i

假如我们的lds文件中有很多变量


lds{

    a1 = ;

    a2 = ;

    a3 = ;

    ...

}


如果我们C程序只用到几个变量,完全没必要全部存储lds里面的所有变量,C程序是不保存lds中的变量的。


对于万一要用到的变量,编译程序时,有一个symbol table符号表:

在这里插入图片描述

如何使用symbol table符号表?

1、对于常规变量g_i,得到里面的值,使用&g_i得到addr;

2、为了保持代码的一致,对于lds中的a1,使用&a1得到里面的值;


结论:

1、C程序中不保存lds文件中的变量,lds再大也不影响;

2、借助symbol table保存lds的变量,使用时加上”&”得到它的值,链接脚本的变量要在C程序中声明为外部变量,任何类型都可以;

推荐阅读

史海拾趣

Catalyst公司的发展小趣事

为了进一步扩大市场份额,Catalyst公司积极实施国际化战略。公司通过与国外知名企业的合作与交流,引进先进的技术和管理经验,不断提升自身的竞争力。同时,Catalyst还积极参加国际电子展会和论坛,展示公司的最新产品和技术成果,吸引了众多国际客户的关注。通过国际化战略的拓展,Catalyst成功打开了海外市场的大门,为公司的长远发展奠定了坚实的基础。

Gulf Semiconductor公司的发展小趣事

Catalyst公司在电子行业的初创期,以其独特的创新理念和前瞻性的技术布局,奠定了坚实的基础。公司创始团队由一群对电子行业充满热情的工程师和科学家组成,他们共同致力于研发高效、稳定的电子产品。通过不断的技术研发和市场调研,Catalyst成功推出了一系列具有竞争力的产品,逐步在市场中崭露头角。

AR RF/Microwave Instrumentation公司的发展小趣事

AR RF/Microwave Instrumentation的创立源于对射频和微波技术的深入研究和理解。公司创始人在行业内具有丰富的经验,他们看到了这一领域的巨大潜力,并决定成立一家公司来专门研发和生产相关的仪器设备。起初,公司规模较小,但凭借高质量的产品和专业的服务,逐渐在行业内赢得了声誉。

Cypress(赛普拉斯)公司的发展小趣事

随着公司业务的不断发展,Cypress开始在全球范围内拓展市场。公司不仅在加州硅谷设立了最早的设计中心,还在美国的其他州以及英格兰、爱尔兰、菲律宾等地设立了设计工厂。此外,Cypress还在菲律宾和印尼设立了组装、检测工厂,形成了全球化的生产网络。这些举措不仅提高了公司的生产效率和产品质量,也进一步巩固了Cypress在全球电子芯片市场的地位。

Advanced Pressure Technology公司的发展小趣事

APT公司成立于1987年,创始人凭借对气体输送技术的深刻理解和前瞻眼光,在加利福尼亚州圣拉斐尔创立了这家公司。初始阶段,公司专注于制造坚固、可靠的气体输送产品,尤其是压力调节器和阀门。尽管市场充满竞争,但APT公司凭借出色的产品性能和可靠的品质,在1988年成功推出了一小部分产品,并迅速获得了市场的认可。销售额的迅速增长和产品供应的紧张,都预示着APT公司正步入快速发展的轨道。

昆泰(CHRONTEL)公司的发展小趣事

多年来,昆泰始终秉持着创新的理念,不断推动其在CRO领域的技术突破和业务创新。通过与全球各地的药企、科研机构合作,昆泰在药物研发、临床试验等领域取得了多项重要成果。展望未来,昆泰将继续坚持创新驱动的发展战略,为全球医药行业的发展做出更大的贡献。

问答坊 | AI 解惑

随机字体时钟

如果你对字体和时钟都有一种狂热的话,这里你就来对了。因为你无法不去注意这种夺人眼球的字体时钟。也许它上面出没的某个字体,会给你的创意工作带来灵感。这种时钟的设计者叫做Sebastian Wrong,姓错了,有点意思。他一共设计出三种不同款式的字 ...…

查看全部问答>

请问WinCE IE收藏夹文件保存在什么位置? (好像在注册表中)

请问WinCE IE收藏夹文件保存在什么位置? (好像在注册表中)…

查看全部问答>

如何让 edit 中的 文字居中显示?

es_center|es_multiline 可以居中,但字与字会重贴在一起,这是什么原因? 有没有别的方法使文字单行居中?…

查看全部问答>

菜鸟求助

请问哪位大侠知道后半段程序有问题吗?用Proteus仿真按键k3不起作用 K1 BIT P2.0                  K2 BIT P2.1 K3 BIT P2.2          &nbs ...…

查看全部问答>

基于DSP技术的MP3播放器的研究与设计

各位高手给点建议,先在这里说谢谢了、…

查看全部问答>

怎么用LM3S811产生任意频率的正弦波

怎么用LM3S811产生任意频率的正弦波…

查看全部问答>

msp430f5529的官方代码的疑惑

 使用此程序后是这个结果:ACLK = REFO = 32.768kHz, MCLK = SMCLK = Default 1MHz include <msp430f5529.h> void main(void){  volatile unsigned int i;   WDTCTL = WDTPW+WDTHOLD;      &n ...…

查看全部问答>

驱动LED恒流IC TM1804

驱动TM1804 LED恒流芯片。需要用到的知识 SPI 或者IO模拟 及有关归零码的知识 http://baike.baidu.com/view/491480.htm  有关归零码的知识 阅读TM1804的芯片手册 后 我选择用SPI的方式去驱动。  该芯片采用归零码方式  如果表示灰 ...…

查看全部问答>

驱动程序安装问题

我的板子在第一次接电脑时显示成功安装驱动程序(COM5),但是后来几次插上去之后电脑都没反应,用IAR下载程序就报错Thu Oct 25, 2012 12:52:31: Fatal error: Failed to initialize.  Check if hardware is connected. Check if drivers ...…

查看全部问答>