资源描述
第5章TMS320C54x软件开发,5.1软件开发过程及开发工具5.2公共目标文件格式5.3常用汇编伪指令5.4链接器命令文件的编写与使用5.5汇编语言程序编写方法5.6TMS320C54xC语言编程5.7用C语言和汇编语言混合编程,5.1软件开发过程及开发工具,1建立源程序2C编译器(CCompiler)3汇编器(Assembler)4连接器(Linker)5调试工具6十六进制转换公用程序(HexConversionUtility),返回首页,图5-1TMS320C54xDSP软件开发流程,表5-1TMS320C54xV3.50版代码生成工具程序,返回本节,5.2公共目标文件格式,5.2.1COFF文件的基本单元段5.2.2汇编器对段的处理5.2.3链接器对段的处理5.2.4重新定位5.2.5程序装入5.2.6COFF文件中的符号,返回首页,5.2.1COFF文件的基本单元段,段(sections)是COFF文件中最重要的概念。一个段就是最终在存储器映象中占据连续空间的一个数据或代码块。目标文件中的每一个段都是相互独立的。一般地,COFF目标文件包含3个缺省的段:text段、data段、bss段。段可以分为两大类,即已初始化段和未初始化段。如图5-2所示为目标文件中的段与目标系统中存储器的关系。,图5-2目标文件中的段与目标存储器的关系,返回本节,5.2.2汇编器对段的处理,1未初始化段未初始化段主要用来在存储器中保留空间,通常将它们定位到RAM中。这些段在目标文件中没有实际内容,只是保留空间而已。程序可以在运行时利用这些空间建立和存储变量。未初始化段是通过使用.bss和.usect汇编伪指令建立的,两条伪指令的句法分别为:.bss符号,字数符号.usect“段名”,字数,2已初始化段已初始化段包含可执行代码或已初始化数据。这些段的内容存储在目标文件中,加载程序时再放到TMS320C54X存储器中。三个用于建立初始化段的伪指令句法分别为:.text段起点.data段起点.sect“段名”,段起点,3命名段命名段就是程序员自己定义的段,它与缺省的.text、.data和.bss段一样使用,但与缺省段分开汇编。data段不同的存储器中,将未初始化的变量汇编到与bss段不同的存储器中。产生命名段的伪指令为:符号.usect“段名”,字数.sect“段名”,段起点,4子段子段(Subsections)是大段中的小段。链接器可以像处理段一样处理子段。采用子段可以使存储器图更加紧密。子段的命名句法为:基段名:子段名子段也有两种,用.sect命令建立的是已初始化段,用.usect命令建立的是未初始化段。,5段程序计数器(SPC)汇编器为每个段安排一个独立的程序计数器,即段程序计数器(SPC)。SPC表示一个程序代码段或数据段内的当前地址。开始时,汇编器将每个SPC置0,当汇编器将程序代码或数据加到一个段内时,相应的SPC增加。如果汇编器再次遇到相同段名的段,继续汇编至相应的段,且相应的SPC在先前的基础上继续增加。,图5-3例5-1产生的目标代码,返回本节,5.2.3链接器对段的处理,链接器对段的处理有两个功能。首先,它将汇编器产生的COFF目标文件(.obj文件)中的各种段作为输入段,当有多个文件进行链接时,它将输入段组合起来,在可执行的COFF输出模块中建立各个输出段。其次,链接器为输出段选择存储器地址。,链接器有两个命令完成上述功能,即:MEMORY命令定义目标系统的存储器配置图,包括对存储器各部分的命名,以及规定它们的起始地址和长度。SECTIONS命令告诉链接器如何将输入段组合成输出段,以及在存储器何处存放输出段。子段可以用来更精确地编排段,可用链接器SECTIONS命令指定子段。,图5-4链接器默认的存储器分配,返回本节,5.2.4重新定位,1链接时重新定位将各个段定位到存储器中,每个段都从合适的地址开始。将符号值调整到相对于新的段地址的数值。调整对重新定位后符号的引用。,2运行时重新定位将代码装入存储器的一个地方,而运行在另一个地方。利用SECTIONS命令选项让链接器定位两次。一些关键的执行代码必须装入在系统的ROM中,但希望在较快的RAM中运行。链接器提供了一个简单的处理该问题的方法。利用SECTIONS命令选项让链接器定位两次。第一次使用装入关键字设置装入地址,再用运行关键字设置运行地址。,返回本节,5.2.5程序装入,(1)硬件仿真器和CCS集成开发环境,具有内部的装入器,调用装入器的LOAD命令即可装入可执行程序。(2)将代码固化在片外存储器中,采用Hex转换工具(Hexconversionutility),例如Hex500将可执行的COFF目标模块(.out文件)转换成几种其他目标格式文件,然后将转换后的文件用编程器将代码写入EPROM/Flash。,返回本节,5.2.6COFF文件中的符号,COFF文件中有一个符号表,用于存储程序中的符号信息。链接器对符号重定位时使用该表,调试工具也使用该表来提供符号调试。外部符号指在一个模块中定义,在另一个模块中使用的符号。可使用.def、.ref或.global汇编伪指令将符号定义为外部符号。.def在当前模块中定义,可以在别的模块中使用的符号;.ref在当前模块中引用,但在别的模块中定义的符号;.global可用于以上任何一种情况。,返回本节,5.3常用汇编伪指令,返回首页,表5-2常用的汇编伪指令,1段定义伪指令为便于链接器将程序、数据分段定位于指定的(物理存在的)存储器空间,并将不同的obj文件链接起来。段的使用非常灵活,但常用以下约定:.text此段存放程序代码。.data此段存放初始化了的数据。.bss此段存入未初始化的变量。.sect名称定义一个有名段,放初始化了的数据或程序代码。,2条件汇编伪指令.if、.elseif、.else、.endif伪指令告诉汇编器按照表达式的计算结果对代码块进行条件汇编。.ifexpression标志条件块的开始,仅当条件为真(expression的值非0即为真)时汇编代码。.elseifexpression标志若.if条件为假,而.elseif条件为真时要汇编代码块。.else标志若.if条件为假时要汇编代码块。.endif标志条件块的结束,并终止该条件代码块。,3引用其他文件和初始化常数伪指令.include文件名将指定文件复制到当前位置,其内容可以是程序、数据、符号定义等。.copy文件名与.include类似。.def符号名在当前文件中定义一个符号,可以被其他文件使用。.ref符号名在其他文件中定义,可以在本文件中使用的符号。.global符号名其作用相当于.def、.ref效果之和。,.mmregs定义存储器映射寄存器的符号名,这样就可以用AR0、PMST等助记符替换实际的存储器地址。.float数1,数2指定的各浮点数连续放置到存储器中(从当前段指针开始)。.word数1,数2指定的各数(十六进制)连续放置到存储器中。.spacen以位为单位,空出n位存储空间。.end程序块结束。,4宏定义和宏调用TMS320C54x汇编支持宏语言。如果程序中需要多次执行某段程序,可以把这段程序定义(宏定义)为一个宏,然后在需要重复执行这段程序的地方调用这条宏。宏定义如下:Macname.macroparameter1,parametern.mexit.endm,返回本节,5.4链接器命令文件的编写与使用,5.4.1MEMORY伪指令及其使用5.4.2SECTIONS伪指令及其使用,返回首页,5.4.1MEMORY伪指令及其使用,MEMORY伪指令就是用来指定目标存储器的模型。MEMORY伪指令的一般语法为:SECTIONSname:property,property,property.name:property,property,property.name:property,property,property.,返回本节,5.4.2SECTIONS伪指令及其使用,SECTIONS伪指令功能如下:说明如何将输入段组合成输出段。在可执行程序中定义输出段。指定输出段在存储器中存放的位置。允许对输出段重新命名。,图5-5例5-6中段的定位,返回本节,5.5汇编语言程序编写方法,5.5.1汇编语言源程序格式5.5.2汇编语言中的常数和字符串5.5.3汇编源程序中的符号5.5.4汇编源程序中的表达式,返回首页,5.5.1汇编语言源程序格式,助记符指令一般包含4个部分,其一般组成形式为:标号:助记符操作数;注释1标号区所有汇编指令和大多数汇编伪指令前面都可以带有标号,标号可以长达32个字符,由AZ、az、09、_、和$符号组成,且第一个字符不能是数字,区分大小写。,2助记符区助记符区不能从第一列开始,否则被认为是标号。3操作数区操作数区是一个操作数列表,可以是常数、符号或常数与符号构成的表达式。操作数间需用“,”号隔开。4注释区注释区可以从任何一列开始,可以包含ASCII字符和空格。,返回本节,5.5.2汇编语言中的常数和字符串,表5-3COFF常数与字符串,返回本节,5.5.3汇编源程序中的符号,1标号2局部标号3符号常数4先定义的符号常数5替代符号,表5-4可以用在表达式中的运算符,表5-5带有绝对符号、可重定位符号的表达式,返回本节,5.5.4汇编源程序中的表达式,表达式可以是常数、符号或由算术运算符结合的常数和符号。表达式值的有效范围为-3276832767。1运算符(表5-4所示)2合格的表达式(表5-5所示),返回本节,5.6TMS320C54xC语言编程,5.6.1存储器模式5.6.2寄存器规则5.6.3函数调用规则5.6.4中断处理5.6.5表达式分析,返回首页,5.6.1存储器模式,1段C54x将存储器处理为程序存储器和数据存储器两个线性块。程序存储器包含可执行代码;数据存储器主要包含外部变量、静态变量和系统堆栈。编译器的任务是产生可重定位的代码,允许链接器将代码和数据定位进合适的存储空间。C编译器对C语言编译后除了生成3个基本段,即.text、.data、.bss外,还生成.cinit、.const、.stack、.sysmem段。,2C/C+系统堆栈.stack不同于DSP汇编指令定义的堆栈。DSP汇编程序中要将堆栈指针SP指向一块RAM,用于保存中断、调用时的返回地址,存放PUSH指令的压栈内容。.stack定义的系统堆栈实现的功能是保护函数的返回地址,分配局部变量,在调用函数时用于传递参数,保护临时结果。.stack定义的段大小(堆栈大小)可用链接器选项-stacksize设定,链接器还产生一个全局符号_STACK_SIZE,并赋给它等于堆栈长度的值,以字为单位,缺省值为1K。,3存储器分配(1)运行时间支持函数。(2)动态存储器分配。(3)静态和全局变量的存储器分配。(4)位域/结构的对准。,返回本节,5.6.2寄存器规则,寄存器规则明确了编译器如何使用寄存器以及在函数调用过程中如何保护寄存器。(1)辅助寄存器(2)堆栈指针SP(3)ARP(4)在默认情况下,编译器总是假定ST1中的OVM在硬件复位时被清0。若在汇编代码中对OVM置位为1,返回到C环境时必须复位。(5)寄存器变量,返回本节,5.6.3函数调用规则,(1)局部帧的产生(2)参数传递(3)函数的返回,返回本节,5.6.4中断处理,(1)中断的使能和屏蔽必须由程序员自己来设置。(2)中断程序没有参数传递,即使说明,也会被忽略(3)中断处理程序不能被正常的C程序调用。(4)为了使中断程序与中断一致,在相应的中断矢量中必须放置一条转移指令,可以用.sect汇编伪指令建立一个简单的跳转指令表来完成此项功能。,(5)在汇编语言中,注意在符号名前面加上一个下划线,例如c_int00记为_c_int00。(6)中断程序使用的所有寄存器,包括状态寄存器和程序中调用函数使用的寄存器都必须予以保护。(7)TMS320C54xC编译器将C语言进行了扩展,中断可以利用interrupt关键字由C/C+函数直接处理。,返回本节,5.6.5表达式分析,当C程序中需要计算整型表达式时,必须注意以下几点:(1)算术上溢和下溢。(2)整除和取模。(3)C代码对16位乘法结果高16位的访问。,返回本节,5.7用C语言和汇编语言混合编程,5.7.1独立的C模块和汇编模块接口5.7.2从C程序中访问汇编程序变量5.7.3在C程序中直接嵌入汇编语句,返回首页,5.7.1独立的C模块和汇编模块接口,在编写独立的汇编程序时,必须注意以下几点:(1)不论是用C语言编写的函数还是用汇编语言编写的函数,都必须遵循寄存器使用规则。(2)必须保护函数要用到的几个特定寄存器。(3)中断程序必须保护所有用到的寄存器。(4)从汇编程序调用C函数时,第一个参数(最左边)必须放入累加器A中,剩下的参数按自右向左的顺序压入堆栈。,(5)调用C函数时,注意C函数只保护了几个特定的寄存器,而其他是可以自由使用的。(6)长整型和浮点数在存储器中存放的顺序是低位字在高地址,高位字在低地址。(7)如果函数有返回值,返回值存放在累加器A中。(8)汇编语言模块不能改变由C模块产生的.cinit段,如果改变其内容将会引起不可预测的后果。,(9)编译器在所有标识符(函数名、变量名等)前加下划线“_”。(10)任何在汇编程序中定义的对象或函数,如果需要在C程序中访问或调用,则必须用汇编指令.global定义。(11)编辑模式CPL指示采用何种指针寻址,如果CPL=1,则采用堆栈指针SP寻址;如果CPL=0,则选择页指针DP进行寻址。,返回本节,5.7.2从C程序中访问汇编程序变量,从C程序中访问在汇编程序中定义的变量或常数,可以分为以下3种情况:(1)访问在.bss块中定义的变量(2)对于访问不在.bss块中定义的变量(3)对于在汇编程序中用.set和.global伪指令定义的全局常数,也可以使用特殊的操作从C程序中访问它们。,返回本节,5.7.3在C程序中直接嵌入汇编语句,在C程序中嵌入汇编语句是一种直接的C模块和汇编模块接口方法。采用这种方法一方面可以在C程序中实现用C语言难以实现的一些硬件控制功能。另一方面,也可以用这种方法在C程序中的关键部分用汇编语句代替C语句以优化程序。采用这种方法的一个缺点是它比较容易破坏C环境,因为C编译器在编译嵌入了汇编语句的C程序时并不检查或分析所嵌入的汇编语句。,返回本节,
展开阅读全文