5311|0

77

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

ALIGN的烦恼和传说中的秘技 [复制链接]

风起 一个ADuC702x(ARM7TDMI)的系统,编译后运行发现这样的问题: // Begin main.c // Some code here... unsigned char bcd[14] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13}; void pro_init(void) { // Some code here... } int main(void) { // Some code here... } // End main.c gcc下编译汇报... -------- begin (mode: ROM_RUN) -------- arm-elf-gcc (GCC) 4.1.2 (WinARM 4/2007) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Size before: main.elf : section size addr .text 436 524288 .data 14 65536 .comment 34 0 Total 484 Errors: none -------- end -------- 云涌 结果main()中测试发现:bcd_buf[0]~bcd_buf[11]有对应初值,而bcd[12]和bcd[13]的值 为0。显然,编译结果有BUG! 经过多次实验,发现改定义为bcd[16],那么bcd[0]至bcd[15] 都有对应初值。gcc编译结果如下: Size before: main.elf : section size addr .text 436 524288 .data 16 65536 .comment 34 0 Total 484 可以看到.data变为16....也就说这是ALIGN(ARM7的RAM是4byte对齐的)方面的BUG.虽然有 这个暂时的回避办法,但这个滥竽充数的招数严重影响我们境界的提升,我们需要更深探索 本源... 惊涛 1)下载gcc使用文档....没找到解法... 2)看startup.S的汇编启动文件... #ifdef ROM_RUN # Relocate .data section (Copy from ROM to RAM) LDR R1, =_etext LDR R2, =_data LDR R3, =_edata CMP R2, R3 BEQ DataIsEmpty LoopRel: CMP R2, R3 LDRLO R0, [R1], #4 STRLO R0, [R2], #4 BLO LoopRel DataIsEmpty: #else #warning RAM_RUN - .data will not be copied #endif # Clear .bss section (Zero init) MOV R0, #0 LDR R1, =__bss_start__ LDR R2, =__bss_end__ LoopZI: CMP R1, R2 STRLO R0, [R1], #4 BLO LoopZI 我们从代码中可以猜出有初值的全局变量被定位在flash,然后拷贝到ram,紧跟着把没有 初值的全局变量(.bss段)全清0...,那么可以断定没有ALIGN的bcd[12]和bcd[13]应该 是被砍头(ALIGN)后清0了... 3)天啊,又要学汇编... 这些定义(_etext,_edata...)在哪里呢?终于找到了,在ADuC7021-ROM.ld 4)我倒!还要学LD Script...来看看ADuC7021-ROM.ld... SECTIONS { /* first section is .text which is used for code */ .text : { *startup.o (.text) /* Startup code */ *(.text) /* remaining code */ *(.glue_7t) *(.glue_7) } >IntFLASH . = ALIGN(4); /* .rodata section which is used for read-only data (constants) */ .rodata : { *(.rodata) } >IntFLASH . = ALIGN(4); _etext = . ; PROVIDE (etext = .); /* .data section which is used for initialized data */ .data : AT (_etext) { _data = . ; *(.data) SORT(CONSTRUCTORS) } >IntRAM . = ALIGN(4); /* take empty data section into account: */ _edata = . ; PROVIDE (edata = .); /* .bss section which is used for uninitialized data */ .bss : { __bss_start = . ; __bss_start__ = . ; *(.bss) *(COMMON) } >IntRAM . = ALIGN(4); __bss_end = . ; __bss_end__ = . ; _end = .; PROVIDE (end = .); /* Stabs debugging sections. */ /* 省略n字 */ } 显然,ALIGN(4)没有起作用,否则,gcc编译应该看到.data不是14而是16... 我请教了n个gcc的高手(至少我认为是)了,可其中90%的都没自己改过 ld script文件...看来我要做剩下的10%...我改...我改...我改改改... SECTIONS { /* first section is .text which is used for code */ .text : { *startup.o (.text) /* Startup code */ *(.text) /* remaining code */ *(.glue_7t) *(.glue_7) . = ALIGN(4) } >IntFLASH /* .rodata section which is used for read-only data (constants) */ .rodata : { *(.rodata) . = ALIGN(4) } >IntFLASH _etext = . ; PROVIDE (etext = .); /* .data section which is used for initialized data */ .data : AT (_etext) { _data = . ; *(.data) SORT(CONSTRUCTORS) . = ALIGN(4) } >IntRAM /* take empty data section into account: */ _edata = . ; PROVIDE (edata = .); /* .bss section which is used for uninitialized data */ .bss : { __bss_start = . ; __bss_start__ = . ; *(.bss) *(COMMON) . = ALIGN(4) } >IntRAM __bss_end= . ; __bss_end__ = . ; _end = .; PROVIDE (end = .); /* Stabs debugging sections. */ /* 省略n字 */ } 变换ALIGN(4)位置后,将bcd[16]定义改回bcd[14],看看gcc编译结果... 彩虹 Size before: main.elf : section size addr .text 436 524288 .data 16 65536 // 注意这里 .comment 34 0 Total 484 下载文件,观察bcd[12]和bcd[13],果然有我们对应的初值了... 兴奋之余,默然回首,发现学了n多东东... gcc的编译参数和Makefile、 arm汇编语言、ld script、obj定位..... 花絮 回头看WinARM的example下所有ld script文件都存在类似的问题... 再想想,如果没有ld script文件,又或startup.S以库形式提供,有没有其它 简便的解决办法呢?有!传说中的秘技:“不要给定义在程序函数外的 全局变量赋初值,而是用单独的初始化函数来在程序内部赋值...” 我想当初第一个说这话的人一定有他的道理,但经过这番折腾后,我 明白了其中大部分的含意,我的境界也许没他高,但对这个问题的看法, 我相信我们的境界大致是一样的... 感谢大家一起分享...
此帖出自单片机论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表