• CCS 的链接器


    一 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

     
  • 相关阅读:
    寒假作业1实践题
    寒假作业1问答题
    (1.21)思考题
    [golang note] 匿名组合
    [golang note] 类型系统
    [golang note] 错误处理
    [golang note] 函数定义
    [golang note] 流程控制
    [golang note] 内建类型
    [golang note] 数组切片
  • 原文地址:https://www.cnblogs.com/zsb517/p/2578381.html
Copyright © 2020-2023  润新知