《DSP原理及应用第四章.ppt》由会员分享,可在线阅读,更多相关《DSP原理及应用第四章.ppt(58页珍藏版)》请在三一办公上搜索。
1、1,第四章 DSP软件开发过程,第一节 汇编语言程序的编写方法 第三节 COFF的一般概念第四节 目标文件的链接,2,软件开发过程,第一节 汇编语言程序的编写方法,3,汇编语言程序的编辑、汇编和链接过程,4,1汇编语言源程序的句法格式,要点,以.asm为扩展名每一行由4个部分组成,格式,标号:空格 助记符 空格 操作数 空格;注释,中的内容为可选择部分,供本程序的其它部分或其它程序调用。标号是任选项,标号后面可以加也可以不加冒号“:”。,5,要 点,1.标号必须从第列写起。2.标号最多可达32个字符,可以是AZ,az,0 9,_,以及$,但标号的第1个字符不能是数字。3.引用标号时,标号的大小
2、写必须一致。4.标号的值就是段程序计数器SPC的值。5.如果不用标号,则第一个字母必须为空格、分号 或星号(*)。,6,要点,建议,标号:空格 助记符 空格 操作数 空格;注释,可以是助记符指令、汇编指令、宏指令和宏调用命令。,1.助记符指令,一般用大写;2.汇编命令和宏命令,以句号“.”开始,且通常用小写。,7,要点,标号:空格 助记符 空格 操作数 空格;注释,1.指令中的操作数或汇编命令中定义的内容 2.操作数之间必须用逗号“,”分开。,1.从分号“;”开始 2.可以放在指令或汇编命令后面,也可以放在单独的一行或数行。,要点,8,汇编语言编写的一般规则为:所有语言必须以标号、空格、星号或
3、分号开始;所有包含汇编伪指令的语句,必须在一行完全指定;可以选择带有标号,若使用标号,则标号必须从第一列开始;每区必须用一个或者多个空格分开,Tab字符键与空格等效;程序中可以有注释,注释开始在第一列时,前面需标上星号或分号,但在其他列开始的注释前面,只能标上分号。,9,2汇编语言源程序的数据型式,二进制:如1110001b或1111001B;八进制:226q或572Q;十进制:1234或+1234或-1234(缺省型)十六进制:0A40h或0A40H或0 xA40浮点数:1.623e-23(仅C语言程序中能用,汇编程序不能用)字符:D字符串:“this is a string”,10,10,
4、常用的汇编命令:,11,例4-1 编写计算y=a1*x1+a2*x2+a3*x3+a4*x4的汇编源程序*example.asm y=a1*x1+a2*x2+a3*x3+a4*x4*.title“example.asm”;为汇编源程序取名.mmregs;定义存储器映象寄存器STACK.usect“STACK”,10h;分配10h个单元的堆栈空间.bss a,4;为系数a分配4个单元的空间.bss x,4;为变量x分配4个单元的空间.bss y,1;为结果y 分配1个单元的空间.def start;定义标号start.data;定义数据代码段table:.word 1,2,3,4;在标号tabl
5、e开始的8个单元中.word 8,6,4,2;为这8个单元赋初值,12,.text;定义文本代码段start:STM#0,SWWSR;软件等待状态寄存器置0,不设等待 STM#STACK+10h,SP;设置堆栈指针初值 STM#a,AR1;AR1 指向 a的地址 RPT#7;从程序存储器向数据存储器 MVPD table,*AR1+;重复传送 8个数据 CALL SUM;调用 SUM 实现乘法累加和的子程序end:B end;循环等待SUM:STM#a,AR3;将系数a的地址赋给AR3 STM#x,AR4;将变量x的地址赋给AR3 RPTZ A,#3;将A清0,并重复执行下条指令4次 MAC*
6、AR3+,*AR4+,A;执行乘法并累加,结果放在A中 STL A,y;将A的低字内容送结果单元y RET;结束子程序.end;结束全部程序,13,4宏定义和宏调用,(1)两者都可以被多次调用,但是把子程序汇编成目标代码的过程只进行一次,而在用到宏指令的每个地方都要对宏指令中的语句逐条地进行汇编。(2)在调用前,由于子程序不使用参数,故子程序所需要的寄存器等都必须事先设置好;而对于宏指令来说,由于可以使用参数,调用时只要直接代入参数就行了。宏指令可以在源程序的任何位置上定义,但必须在用到它之前先定义好。宏定义可以嵌套。,宏指令与子程序的异同,14,macname.macroparameter
7、1,parameter n 助记符指令与宏指令.mexit.endm,宏定义的格式,宏调用的格式,label:macname parameter1,parametern,15,1*23*add34*5*ADDRP=P1+P2+P3;说明宏功能67 add3.macro p1,p2,p3,ADDRP;定义宏89 LD p1,A;将参数1赋给A10 ADD p2,A;将参数2与A相加11 ADD p3,A;将参数3与A相加12 STL A,ADDRP;将结果A的低字存参数413.endm;结束宏141516.global abc,def,ghi,adr;定义全局符号1718 000000 add3
8、 abc,def,ghi,adr;调用宏11 000000 1000!LD abc,A;宏展开1 000001 0000!ADD def,A 1 000002 0000!ADD ghi,A1 000003 8000!STL A,adr,例4-2 宏定义、宏调用和宏展开的一个例子。,16,汇编器和连接器建立的目标文件,是一个可以在TMS320C54x器件上执行的文件,这些文件的格式称之为公共目标文件格式,即COFF。COFF会使模块编程和管理变得更加方便。,第三节 COFF的一般概念,17,特点,定义,分段的优点:在目标文件中将放置程序、数据、变量的代码分开,便于在链接时作为一个单独的部分分配存
9、储器。由于大多数系统都有好几种形式的存储器,通过对各个段重新定位,可以使目标存储器得到更为有效的利用。,段是在存储器图中占据相邻空间的代码或数据块。,一个目标文件中的每一个段都是分开的和不相同的。,目标文件中的段与目标存储器之间的关系,1COFF文件中的段,18,2外部符号的概念,用于处理符号的汇编命令,外部符号,在一个模块中定义,可在另一个模块中引用的符号。,19,x:ADD#56h,A;定义x B y;引用y.def x;x在此模块中定义,;可被别的模块引用.ref y;y在这里引用,;它在别的模块中定义,注意,汇编时,汇编器把x和y都放在目标文件的符号表中。链接器必须使所引用的符号与相应
10、的定义相匹配。如果链接器不能找到某个符号的定义,就给出不能辨认所引用符号的出错信息。,20,3汇编器对段的处理,用于定义段的汇编命令,.bss 未初始化段.usect 未初始化自定义段.text 已初始化程序正文段.data 已初始化程序数据段.sect 已初始化自定义段,如果汇编语言程序中一个段命令都没有用,那么汇编器把程序中的内容都汇编到.text段。,21,(1)未初始化段,未初始化段由.bss和.usect命令建立,位置,为变量保留存储器空间,作用,通常将它们定位到RAM区,使用方法,.bss 符号,字数 符号.usect“段名”,字数,对应于保留的存储空间第一个字的变量名称,程序员为
11、自定义未初始化段起的名字,22,(2)已初始化段,已初始化段是由.text、.data的.sect命令建立,位置,包含有可执行代码或初始化数据,作用,通常将它们定位到EPROM区,使用方法,.text 段起点.data 段起点.sect“段名”,段起点,段程序计数器(SPC)定义的一个起始值。,程序员为自定义已初始化段起的名字,23,(3)子段,位置,子段结构,可以使存储器分配图更加紧密。,可单独分配空间或在基段位置之后,使用方法,基段名:子段名.sect“.text:_func”,子段也有两种:用.sect命令建立的是已初始化段,而用.usect命令建立的段是未初始化段。,作用,24,(4)
12、段程序计数器(SPC),编址过程,表示一个程序代码段或数据段的当前地址,作用,汇编器为每个段都安排了一个单独的程序计数器称之为段程序计数器SPC。一开始,汇编器将每个SPC置0。当汇编器将程序代码或数据加到一个段内时,相应的SPC就增加。如果再继续对某个段汇编,则相应的SPC就在先前的数值上继续增加。链接器在链接时要对每个段进行重新定位。,25,当汇编器遇到.text或.data或.sect命令时,将停止对当前段的汇编(相当于一条结束当前段汇编的命令),然后将紧接着的程序代码或数据汇编到指定的段中,直到再遇到另一条.text、.data或.sect命令为止。当汇编器遇到.bss或.usect命
13、令时,并不结束当前段的汇编,只是暂时从当前段脱离出来,并开始对新的段进行汇编。,(5)汇编器对段的处理,26,段命令应用举例,汇编语言源程序:,.datacoeff.word 044h,055h,066h.bss buffer,8 prt.word 0456h.textadd:LD 0Dh,A aloop:SUB#1,A BC aloop,AGEQ.dataivals.word 0CCh,0DDh,0EEh,;初始化数据段;3组数据放入.data段;在.bss段保留8个单元;0456h放入.data段;初始化文本段;1字指令;2字指令;2字指令,共计5个字,;初始化数据段;3组数据放入.dat
14、a段,27,汇编语言源程序:,var2.usect“newvars”,2 inbuf.usect“newvars”,8.text mpy:LD 0Ah,B mloop:MPY#0Ah,B BC mloop,BNOV.sect“vectors”.word 044h,088h,;建立newvars命名段,保留2个单元;在newvars段保留8个单元;初始化文本段;1字指令;2字指令;2字指令,共计5个字,;建立vectors命名段;2组数据放入vectors命名段,28,经汇编后,得列表文件(部分):,2*3*汇编一个初始化表到.data段*4*5 0000.data6 0000 0044 coe
15、ff.word 044h,055h,066h 0001 0055 0002 00667*8*在.bss段中为变量保留空间*9*10 0000.bss buffer,811*12*仍然在.data 段中*13*14 0003 0456 prt.word 0456h,5 0000.data,6 0000 0044 coeff.word 044h,055h,066h,10 0000.bss buffer,8,14 0003 0456 prt.word 0456h,.data,6,0044,6,0055,6,0066,10,.bss,没有数据保留8个字,14,0456,29,15*16*汇编代码到.t
16、ext段*17*18 0000.text19 0000 100d add:LD 0Dh,A20 0001 f010 aloop:SUB#1,A 0002 0001 21 0003 f842 BC aloop,AGEQ 0004 0001 22*23*汇编另一个初始化表到.data 段*24*25 0004.data 26 0004 00cc ivals.word 0CCh,0DDh,0EEh 0005 00dd 0006 00ee27*28*为更多的变量定义另一个段*29*30 0000 var2.usect“newvars”,2 31 0001 inbuf.usect“newvars”,8,
17、.text,18 0000.text,19 0000 100d add:LD 0Dh,A,19,100d,20 0001 f010 aloop:SUB#1,A,20,f010,20,0001,21 0003 f842 BC aloop,AGEQ,21,f842,21,0001,25 0004.data,26 0004 00cc ivals.word 0CCh,0DDh,0EEh,.data,26,00cc,26,00dd,26,00ee,30 0000 var2.usect“newvars”,2,newvars,30,保留2个字,31 0001 inbuf.usect“newvars”,8,3
18、1,保留8个字,30,32*33*汇编更多代码到.text段*34*35 0005.text 36 0005 110a mpy:LD 0Ah,B 37 0006 f166 mloop MPY#0Ah,B 0007 000a 38 0008 f868 BC mloop,BNOV 0009 0006 39*40*为中断向量.vectors定义一个自定义段*41*42 0000.sect“vectors”43 0000 0044.word 044h,088h 0001 0088,35 0005.text,.text,36 0005 110a mpy:LD 0Ah,B,36,110a,37 0006
19、f166 mloop MPY#0Ah,B,37,f168,37,000a,38 0008 f868 BC mloop,BNOV,38,f868,38,0006,42 0000.sect“vectors”,vectors,43 0000 0044.word 044h,088h,43,0044,43,0088,31,汇编语言源程序经过汇编后,共建立了5个段:.text段文本段,段内有10个字可执行 的程序代码。.data段已初始化的数据段,段内有7 个字的数据。vectors段用.sect命令生成的命名段,段内有2个字的初始化数据。.bss段未初始化的数据段,在存储器中 为变量保留8个存储单元。n
20、ewvars段用.usect命令建立的命名段,为变量保留10个存储单元。,32,第四节 目标文件的链接,链接器主要功能,根据链接命令和链接命令文件(.cmd文件),将一个或多个COFF目标文件链接起来,生成存储器映象文件(.map)和可执行的输出文件(.out)(COFF目标模块),33,1运行链接程序,键入命令lnk500 file1.obj file2.obj o,链接器是名为lnk500.exe 的可执行程序,34,2.链接器对段的处理,(1)把一个或多个COFF目标文件中的各种段作为链接器的输入段,经链接后在一个可执行的COFF输出模块中建立各个输出段。(2)为各个输出段选定存储器地址
21、。也就是对每个段进行重定位。,链接器在对目标文件进行处理时,主要完成,35,(1)链接时重新定位 汇编器对每段汇编时都是假定其起始地址为0,每段中所有的重定位符号(标号)都是相对于0地址而言的。实际上,并不是所有段在存储器中都是以0地址起始的,因此连接器必须通过下列方法对每段进行重定位将各个段定位到存储器中,每个段都从合适的地址开始。将符号值调整到相对于新的段地址的数值。调整对重新定位后符号的引用。,36,例4-5 列表文件中,汇编器为需要重新定位的符号所留的重定位入口。1 0100 X.set 0100h;给X赋值2 0000.text3 0000 FO73 B Y;生成一个重定位入口 00
22、00 00044 0002 F020 LD#X,A;生成一个重定位入口 0003 0000!5 0004 F7E0 Y:RESET,在.text段对X的引用是一次外部引用,37,假设链接时X重新定位在地址7100h,.text段重新定位到从地址7200h开始,那么Y的重定位值为7204h。链接器利用两个重定位入口,对目标文件中的两次引用进行修正:f073 B Y 变成 f073 0004 7204 f020 LD#X,A 变成 f020 0000!7100在COFF目标文件中有一张重定位入口表。链接器在处理完之后就将重定位入口消去,以防止在重新链接或加载时再次重新定位。,一个没有重定位入口的文
23、件称为绝对文件,它的所有地址都是绝对地址。,38,(2)运行时重新定位 将代码装入存储器的一个地方,而运行在另一个地方。一些关键的执行代码必须装入在系统的ROM中,但希望在较快的RAM中运行。链接器提供了一个简单的处理该问题的方法。利用SECTIONS命令选项让链接器定位两次。第一次使用装入关键字设置装入地址,再用运行关键字设置运行地址。在应用中将该段从装入地址复制到运行地址。,39,3.链接器命令文件,是由两个链接器命令MEMORY和SECTIONS构成的文件主要实现两个功能:(1)对存储器进行配置(2)对各个输出段进行重新定位,40,例4-6 链接器命令文件举例。a.obj b.obj/*
24、输入文件名*/-o prog.out/*选项*/-m prog.map/*选项*/MEMORY/*MEMORY 命令*/PAGE0:ROM:origin=1000h,length=0100h PAGE1:RAM:origin=0100h,length=0100hSECTIONS/*SECTIONS 命令*/.text:ROM.data:ROM.bss:RAM,41,4两条链接器命令的使用方法,MEMORY命令用来定义目标系统中所包含的各种形式的存储器的存储器配置图,包括对存储器各部分命名,以及规定它们的起始地址和长度。,(1)MEMORY命令,功能,42,MEMORY PAGE 0:name
25、1(attr):origin=constant,length=constant PAGE n:name n(attr):origin=constant,length=constant,MEMORY命令的一般句法,对一个存储空间加以标记,每一个PAGE代表一个完全独立的地址空间。页号n最多可规定为255,取决于目标存储器的配置。通常PAGE 0定为程序存储器,PAGE 1定为数据存储器。如果没有规定PAGE,则链接器就将目标存储器配置在PAGE 0。,43,MEMORYPAGE 0:name 1(attr):origin=constant,length=constantPAGE n:name n
26、(attr):origin=constant,length=constant,名字可以包含8个字符,AZ、az、$、.、_均可。名字并没有特殊的含义,用来标记存储器的区间而已;名字都是内部记号,不需要保留在输出文件或者符号表中。不同PAGE上的存储器区间可以取相同的名字,但在同一PAGE内的名字不能相同,且不许重叠配置。,44,MEMORYPAGE 0:name 1(attr):origin=constant,length=constantPAGE n:name n(attr):origin=constant,length=constant,任选项,为命名区规定14个属性。如果有选项,应写在括
27、号内。当输出段定位到存储器时,可利用属性加以限制。,规定一个存储区的起始地址。键入origin、org或o都可以。这个值是一个16位二进制常数,可以用十进制数、八进制数或十六进制数表示。,规定一个存储区的长度,键入length、len或l都可以。,45,R 规定可以对存储器执行读操作。W 规定可以对存储器执行写操作。X 规定存储器可以装入可执行的程序代码。I 规定可以对存储器进行初始化。任何一个没有规定属性的存储器都默认有全部4项属性。fill:任选项,不常用,在句法中未列出,为没有定位输出段的存储器空单元填充一个数,键入fill或f均可。这是2个字节的整型常数,可以是十进制数、八进制数或十六
28、进制数表示。如fill=0FFFFh。,属性选项一共有4项,46,例4-7 MEMORY命令的使用方法。/*Example command file with MEMORY directive*/file1.obj file2.obj/*Input files*/-o prog.out/*Options*/MEMORY PAGE0:ROM:origin=COOh,length=1000h PAGE1:SCRTCH:origin=60h,length=20h ONCHIP:origin=80h,length=200h,名为ROM的程序存储器:4K字ROM,起始地址C00h。,名为SCRATCH的
29、数据存储器:32字RAM,起始地址60h。名为ONCHIP的数据存储器:512字RAM,起始地址为80h。,47,告诉链接器如何将输入段合成输出段在可执行程序中定义输出段规定输出段在存储器中的存放位置允许重新命名输出项。,(2)SECTIONS命令,功能,在链接器命令文件中,SECTIONS命令用大写字母,紧随其后并用大括号括起来的是关于输出段的详细说明。每一个输出段的说明都从段名开始。段名后面是一行说明段的内容和如何给段分配存储单元的性能参数。,48,SECTIONSname:property,property,property,name:property,property,property
30、,name:property,property,property,SECTIONS命令的一般句法,性能参数,1)load allocation 定义将输出段加载到存储器中的 什么位置。句法:load=allocation 或者用大于号代替“load=”allocation 或者省掉“load=”allocation其中allocation是关于输出段地址的说明,即给输出段分配存储单元。,49,.text:load=0 x1000 将输出段.text定位到一个特定地址。.text:ROM 将输出段.text定位到名为ROM的存储区。.bss:(RW)将.bss段定位到属性为R、W的存储区。.te
31、xt:align=0 x80 将.text定位到0 x80开始的存储区。.bss:load=block(0 x80)将.bss定位到一个n字存储器 块的任何一个位置(n为 2的幂次)。.text:PAGE 0 将输出段.text定位到PAGE 0。如果要用到一个以上参数,可以将它们排成一行,例如:.text:ROM align(16)PAGE(2)或者为方便阅读,可用括号括起来:.text:load=(ROM align(16)PAGE(2),50,2)Run allocation 用来定义输出段在存储器的 什么位置上开始运行。句法:run=allocation 或者用大于号代替等号runal
32、location链接器为每个输出段在目标存储器中分配两个地址:一个是加载的地址,另一个是执行程序的地址。通常,这两个地址是相同的,可以认为每个输出段只有一个地址。有时要想把程序的加载和运行区分开(先将程序加载到ROM,然后在RAM中以较快的速度运行),只要用 SECTIONS命令让链接器对这个段定位两次就行了。一次是设置加载地址,另一次是设置运行地址。例如:.fir load=ROM,run=RAM,51,3)Input sections 用来定义由哪些输入段组 成输出段。句法:input_sections大多数情况下,在SECTIONS命令中是不列出每个输入文件的输入段的段名的:SECTIO
33、NS.text:.data:.bss 这样,在链接时,链接器就将所有输入文件的.text段链接成.text输出段,其它段也一样。,52,SECTIONS.text:/*建立.text 输出段*/f1.obj(.text)/*链接源于f1.obj的.text段*/f2.obj(sec1)/*链接源于f2.obj的sec1段*/f3.obj/*链接源于f3.obj的所有段*/f4.obj(.text,sec2)/*链接源于f4.obj的.text 段和sec2段*/,用文件名和段名来明确地规定输入段,53,如果没有利用MEMORY和SECTIONS命令,链接器就按默认算法来定位输出段:MEMORY
34、PAGE 0:PROG:origin=0 x0080,length=0 xFF00PAGE 1:DATA:origin=0 x0080,length=0 xFF80SECTIONS.text:PAGE=0.data:PAGE=0.cinit:PAGE=0.bss:PAGE=1,(3)MEMORY和SECTIONS命令的默认算法,所有的.text输入段,链接成一个.text输出段,它是可执行的输出文件;,所有的.data输入段组合成.data输出段,所有的.bss输入段则组合成一个.bss输出段,.text和.data段定位到配置为PAGE 0上的存储器,即程序存储空间。,54,6多个文件的链接
35、,例4-8 编写复位向量文件vextors.asm。*Reset vector for example.asm*.title“vectors.asm”.ref _c_int00.sect“.vectors”B _c_int00.end,引用example.asm中.def _c_int00定义的标号,编写example.asm见例4-1。,55,编写example.asm.,*example.asm y=a1x1+a2x2+a3x3+a4x4*.title example.asm.mmregsSTACK.usectSTACK,10H;allocate space for stack.bss a
36、,4;allocate 9 word for variants.bss x,4.bss y,1.def start.datatable:.word 1,2,3,4;data follows.word 8,6,4,2.text;code follows._c_int00:STM#0,SWWSR;adds no wait states STM#STACK+10H,SP;set stack pointer STM#a,AR1;AR1 point a RPT#7;move 8 values MVPD table,*AR1+;from program memory;into data memory CA
37、LL SUM;call SUM subroutineend:B endSUM:STM#a,AR3;The subroutine implement STM#x,AR4;multiply-accumulate RPTZ A,#3 MAC*AR3+,*AR4+,A STL A,y RET.end,56,假设目标存储器的配置如下:程序存储器:EPROM E000hFFFFh(片外)数据存储器:SPRAM 0060h007Fh(片内)DARAM 0080h017Fh(片内)例4-9 根据例4-1和例4-8编写链接器命令文件example.cmd。vectors.objexample.obj-o exa
38、mple.out-m example.map,生成一个映象文件example.map,生成可执行的输出文件example.out,汇编生成目标文件example.obj和vectors.obj,57,MWMORY PAGE 0:EPROM:org=0E000h,len=100h VECS:org=0FF80h,len=04h PAGE 1:SPRAM:org=0060h,len=20h DARAM:org=0080h,len=100hSECTIONS.text:EPROM PAGE 0.data:EPROM PAGE 0.bss:SPRAM PAGE 1 STACK:DARAM PAGE 1.vectors:VECS PAGE 0,58,链接后生成一个可执行的输出文件example.out和映象文件 example.map。映象文件中给出了存储器的配置情况、程序文本段、数据段、堆栈段、向量段在存储器中的定位表,以及全局符号在存储器中的位置。可执行输出文件example.out装入目标系统后就可以运行了。系统复位后,PC首先指向00FF80h,这是复位向量地址。在这个地址上,有一条B _c_int00指令,程序马上跳转到_c_int00语句标号,从程序起始地址0e000h开始执行主程序。,