TI公司新的汇编器和编译器创建的目标文件采用COFF(Common Object File Format)的目标文件格式。采用COFF格式有利于模块化编程,为管理代码段和目标系统存储器提供更加有力和灵活的方法。基于COFF格式编写汇编程序或C语言程序时,不必为程序代码和变量指定目标地址;为程序编写和程序移植提供了极大的方便。
COFF格式的基本思想是:鼓励程序员在用汇编语言或C语言编程时运用代码块和数据块的概念。这种块称为SECTION,是目标文件中的最小单位。
所有的块分为两大类:已初始化块和未初始化块。已初始化块包含程序代码和数据,未初始化块是为未初始化的数据在存储器中的保留块。
C编译器对C程序编译后产生已初始化块和未初始化块,已初始化块如.text块、.const块、.cinit块;未初始化块如.bss块。
举个例子,当程序员用C语句float data[100];定义一个数组时,不需要指定这100个数组元素的具体位置,编译器会在数据区预留所需空间。到链接时链接器会具体定位。
1 链接器对块的处理
链接器对块的处理有两个功能:其一,将COFF目标文件中的块用来建立程序块和数据块,并将这些块组合成可以被DSP芯片执行的COFF输出模块;其二,链接器为输出块指定存储位置。
链接器提供两个命令实现上述功能:MEMORY和SECTIONS。
MEMORY命令定义目标系统的存储器,程序员可以定义每一块存储器并指定起始地址和长度;
SECTIONS命令用来定义输入块的组合和输出块在存储器中的存放位置。
若不用MEMORY和SECTIONS命令,链接器采用缺省的分配算法。推荐使用这两个命令,但要注意这两个命令在CMD文件(链接器命令文件)中使用。
下面分析一个TMS320F240芯片的典型CMD文件。(假设文件名 EX1.CMD。)
(1)CMD文件的构成及其详细解释
BOOT.OBJ
/*F240的中断矢量表,参见后面的说明*/
EX1.OBJ
/*源程序编译后对应的目标文件*/
/*若程序有多个目标文件,一块写在这里*/
-STACK 0X400
/*设定系统堆栈*/
-C
/*ROM初始化*/
-O EX1.OUT
/*输出的文件名*/
-M
EX1.MAP
/*输出映像文件名*/
-L RTS2XX.LIB
/*涟接RTS2XX.LIB库*/
MEMORY /*MEMORY命令规定系统的存储器配置*/
{
PAGEO:ROM0:origin=0000h,length=003fh
/*FLASH ROM*/
PAGE0:ROM1:origin=0040h,length=0200h
/*FLASH ROM*/
PAGEO:ROM2:origin=0240h,length=3000h
/*FLASH ROM*/
PAGE1:RAM_B2:origin=0060h,length=0020h
/*内部RAMB2*/
PAGE1:RAM_B1:origin=0300h,length=0100h
/*内部RAM B1*/
PAGE1:RAM_B0:origin=0100h,length=0100h
/*内部RAM B0*/
PAGE1:RAM_EX:origin=0d000h,length=2800h
/*外部扩展RAM*/
}
SECTIONS
/*SECTIONS命令规定了程序中块的具体分配方法*/
{
.vectors:load=ROM0 /*规定矢量表的存放位置*/
.cinit:load=rom1
/*C初始化表的存放位置*/
.text:
load=ROM2
/*系统程序的存放位置*/
.bSS
load=RAM_B0
/*未初始化数据的存放位置*/
.const
load=RAM_B1
*已初始化数据的存放位置*/
}
(2)TMS320F240链接时所需的中断矢量表文件
TMS320F240的目标文件在链接时要用到中断矢量表。中断矢量表用汇编语言编写,和具体的DSP芯片有关。假设TMS320F240的中断矢量表对应的汇编程序为BOOT.ASM,汇编后的文件名为BOOT.OBJ。
下面是一个典型的矢量表文件。(假设程序名为BOOT.ASM。)
.port /*定义中断函数的名字*/
.globl_c_int0 /*中断0对应的函数名*/
.globl_c_int1
/*中断1对应的函数名,以下语句的意义相同*/
.globl_c_int2
/*可以将中断函数名看作中断入口地址*/
.globl_c_int3
/*矢量表的存放不需程序员干预*/
.globl_c_int4
.globl_c_int5
.globl_c_int6
.globl_c_int7
.globl_c_int8
·sect“.vectors”/*用.sect命令自定义一个块,用于存放中断矢量表*/
RSVECT B
_c_int0
/*中断0发生后,程序的跳转目的地址*/
INT1
B
_c_int1 /*中断1发生后,则跳到c_int1()函数处*/
INT2
B
_c_int2 /*意义同上,下同*/
INT3 B
_c_int3
INT4 B
_c_int4
INT5 B
_c_int5
INT6 B
_c_int6
用汇编器汇编该程序,命令形式:DSPABOOT.ASM-V2XX生成BOOT.OBJ文件供链接器使用。这样,就可以按如下形式在C源程序中编写中断函数:
voidc_inx() /*x为1~8中之一*/
{
中断程序的C语句系列;
}
注意事项:c_int0()是系统入口函数,用户不能编写。
经过上面对命令文件(CMD文件)和中断矢量表的介绍,接下来可以链接命令文件来生成所需要的OUT文件供DSP芯片执行或进行软仿真。
命令形式:DSPLNK CMD文件名
例如:DSPLNK EX1.CMD
另一种情况是,不使用CMD文件,使用缺省配置,简单介绍如下:
命令形式:DSPLNK OBJ文件名参数
例如:DSPLNK EX1.OBJ BOOT.OBJ-O XX1.OUT-M XX1.MAP
以上三步可以用图1描述。