编程浪子的博客

碌碌无为终为过

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

一 CCS链接器的作用和过程

汇编器已经将源文件(.asm)顺序地按段的定义(SPC)转换 成机器语言目标文件(.obj文件),即COFF文件, 连接器的主要任务是根据连接命令或连接命令文件(.cmd)将一个或多个 COFF目标文件连接起来,生成存储器映象文件(.map)和可执行的输出 文件(.out文件),即COFF目标模块。 链接过程为:

(1)将各个目标文件合并起来,将各个文件的各个段配置到目标系统的存储器中

(2)对各个符号和段进行重定位,并给它们指定一个最终的地址

(3)解决输入文件之间未定义的外部引用 。

二 链接命令文件的写法

coff(公共目标文件格式,Common object file format)文件格式是基于块(section)的概念建立的,即程序被分解成各种块的组合体:如文本块、数据块等。 具有一下特点:

(1)便于实现模块化程序设计

(2)为管理代码块和目标系统存储器提供更强有力和更加灵活的方法

(3)程序员设计时只需基于代码块和数据块等概念进行,不需关注每条命令或每个数据的具体目标地址。至于它们的最终将处于存储器的哪个位置,将由链接器来安排

(4)为程序编写和移植提供了很大的方便

1 section

Section目标文件中最小单位称为块。一个块就是最终在存储器映象中占据连续空间的一段代码或数据。所有的section按照是否自定义可以分为:

(1)Coff默认的section (2)自定义的section ,按照是否初始化可以分为:(1)初始化的section(2)未初始化的section 。C语言和汇编中可能有些不同。

汇编器中默认的section有:

section 作用 通常位置

.text

通常包含可执行代码

RAM或者EPROM

.data

通常包含已初始化数据

ROM或者EPROM

.bss

通常用来为未初始化变量保留

RAM

汇编中自定义模块可以通过.sect 创建具可重定位地址的命名块 和.usect创立未初始化块。

C语言的section可以区分如下:

section 作用

.text

可代码和常数

.cinit

变量初值表
.switch 用于大型switch语句的跳转表

.const

常量和字符串
   
.bss 全局变量和静态变量
.system 全局堆(用于存储器的分配)
.stack 堆栈
.far 以far声明的全局和静态变量
.cio 用于stdio函数
.ebss 长调用的.bss(超过了64K地址限制)
.esysmem 长调用的.sysmem(超过了64K地址限制)
econst 长.const(可定位到任何地方)

当然,C语言中可以自定义段

2.CMD

链接器有两种定位快的办法,一种是采用默认的分配算法,汇编中的过程如下:

(1)假定存储器的起始地址为0

(2)假定有2^32字的存储器可以用来分配

(3)将.text分配到起始地址为0的程序存储器中

(4)将.data分配到紧接着.text的程序存储器中

(5)将.bss分配到紧接着.data的程序存储器中

(6)分配自定义的section。

连接器也可以通过链接命令文件来完成,CMD文件由三部分组成

(1) 输入输出定义;

这一部分,可以通过ccs的“Build Option........”菜单设置。主要包含以下几个部分:

1

具体的指令有:

-a 产生绝对地址(不可重新定位)的可执行模块,若没有指定-a或-r,默认情况为-a
-r 产生可重新定位不可执行的模块
-ar 产生可重新定位可执行的模块
-b 连接器将不合并任何由于多个文件而可能存在的重复符号表项,此项选择的效果是使连接器运行较快,但其代价是输出的COFF文件较大
-c 使用由TMS320C54x C/C++编译器的ROM自动初始化模型所定义的连接约定
-cr使用由C编译器的RAM自动初始化模型所定义的连接约定
-e global_symbol 定义全局符号为输出模块的指定主入口点
-f fill value为输出段中空洞设定默认的填充值, fill value为16位的常数
 -h 使所有的全局符号为静态变量
-g global_symbol保持指定的global_symbol为全局符号,而不管是否使用了-h选项
-help , -? 显示所有可利用的连接命令行选项
-head size为C语言的动态存储器分配设置堆栈大小,以字为单位,并定义指定的堆栈大小的全局符号,size有默认值为1k字
-i  dir 改变库搜索方法为在搜索默认的位置前先搜索dir ,该项必须在-l(L)选项之前出现
-l  filename  指定一个存档库文件为连接器的输入 , filename为存档库文件名,该选项必须在-i 选项之后出现,目录或文件名必须遵守操作系统的规定
-m filename  产生一个存储器(地址)映射文件,输出名为filename.map , 该文件列出了输入和输出段(包括空洞)的地址
-o filename 指定可执行输出模块的文件名(filename) , 默认为a.out , 目录或文件名必须遵守操作系统的规定
-q 请求静态运行(quiet run) ,即压缩旗标(banner)必须是在命令行的第一个选项
-s 从输出模块中去掉符号表信息和行号
-stack  size 设置C系统堆栈,大小以字为单位,并定义指定堆栈大小的全局符号,默认的size为1k
-u symbol 将不能分辩的外部符号放入输出模块的符号表
-vn 指定产生的COFF文件格式n , n=0、1或2,默认为COFF2
-w 当出现没有定义的输出段时,发出警告
-x 迫使重读库,以分辩后面的引用
(2) MEMORY命令;

MEMORY: 定义目标系统的存储器映象,可以给它们命名,规定起始地址和长度

用法:MEMORY { 存储器空间名:o = 十六进制存储器起始地址 l = 十六进制存储器长度 }

例如:

 MEMORY                                         
 {                                              
     L2RAM:      o = 0x10800000  l = 0x00020000 
     DDR2:       o = 0x80000000  l = 0x10000000 
 }   

(3) SECTION命令。

SECTIONS:指定怎样组合各输入块以及将各输出块存放在存储器 的哪个位置

用法:

sections 
{
 段名1 > 存储器空间名1 
 段名2 > 存储器空间名2 
.
.
.
}

例子:

 SECTIONS                                       
 {                                              
     .bss        >   L2RAM                      
     .cinit      >   L2RAM                      
     .cio        >   L2RAM                      
     .const      >   L2RAM                      
     .data       >   L2RAM                      
     .far        >   L2RAM                     
     .stack      >   L2RAM                   
     .switch     >   L2RAM                   
     .sysmem     >   L2RAM                 
     .text       >   L2RAM               
     .ddr2       >   DDR2            
 }                                  

 

CMD中也可以自定义section,用法如下:

#pragma DATA_SECTION(函数名或全局变量名,"用户自定义在数据空间的段名");

#pragma CODE_SECTION(函数名或全局变量名,"用户自定义在程序空间的段名");

具体用法如下:

sections
{
       段名1   >  存储器空间名1
       段名2   >  存储器空间名2
}
 
可以参开网址:CMD
posted on 2012-09-13 17:41  编程浪子_  阅读(5264)  评论(0编辑  收藏  举报