《TMS320C3X系列-DSP原理与开发技术》课件第4章_第1页
《TMS320C3X系列-DSP原理与开发技术》课件第4章_第2页
《TMS320C3X系列-DSP原理与开发技术》课件第4章_第3页
《TMS320C3X系列-DSP原理与开发技术》课件第4章_第4页
《TMS320C3X系列-DSP原理与开发技术》课件第4章_第5页
已阅读5页,还剩156页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章TMS320C3x汇编语言指令

与命令文件

4.1汇编伪指令4.2TMS320C3x汇编语言指令4.3公共目标文件格式4.4命令文件

本章小结

思考题和习题4.1汇 编 伪 指 令

汇编伪指令提供程序数据,控制汇编过程,用户可以用它们来完成以下任务:将代码和数据汇编到特定的段(对于段的概念见后续内容);为初始化的便利保留存储器的空间;控制列表的形式;存储器初始化;汇编条件块;定义全局变量;指定汇编器可以获得宏的特定库;检查符号调试信息。

C3x常用的汇编伪指令如下:.end ;程序结束标志.float ;定义1个或多个单精度浮点常数.set ;定义1个或多个常数或符号.global ;定义全局变量或数据块.space ;编译时自动产生的空行数.word ;定义整型数据或数组.text ;程序代码段.bss ;为初始化变量保留存储空间段

.data ;初始化数据段

.sect ;已初始化可重定位的段

.usect ;未初始化具有绝对地址的段当然还有其它的一些不常用的伪指令,可查阅TI公司的相关手册。4.2TMS320C3x汇编语言指令

4.2.1数据传输指令

TMS320C3x支持13条数据传输指令,可以实现寄存器之间、存储器之间以及寄存器与存储器之间的数据传输和存储。这些指令的指令格式、用途、操作及其说明如表4.1所示。指令中的源操作数可通过寄存器寻址、直接寻址、间接寻址(disp=0~255,IR0,IR1)和立即寻址这四种通用的寻址方式给出。表4.1数据传输指令例4.1浮点指数的装载。如:LDER0,R6指令执行前 指令执行后

R0=0200056F30 R0=0200056F30

R6=0857682386 R6=0257682386例4.2条件装载浮点数。如:LDFCR1,R2指令执行前 指令执行后

R1=2CFF789634 R1=2CFF789634

R2=5F234B6780 R2=2CFF789634

C=1

C=1例4.3装载整型数。如:LDI*++AR1(IR1),R8指令执行前 指令执行后

R8=1000h R8=123h

AR1=809800h AR1=809805h

IR1=5h IR1=5h

(809805h)=123h (809805h)=123h例4.4装载数据页指针。如:LDP@809806h,DP指令执行前 指令执行后

DP=60h

DP=80h例4.5弹出堆栈。如:POPR3指令执行前 指令执行后

R3=123h R3=5h

SP=09802h SP=809801h

(809802h)=5h (809802h)=5h例4.6压入堆栈。如:PUSHR3指令执行前 指令执行后

R3=123h

R3=123h

SP=809802h

SP=809803h

(809803h)=5h

(809803h)=123h例4.7存储整数。如:STIR4,@9700h指令执行前 指令执行后

R4=123h R4=123h

DP=80h DP=80h

(809700h)=5h (809700h)=123h4.2.2二操作数指令所谓的二操作数,是指源操作数和目的操作数。源操作数可以通过寄存器寻址、直接寻址、间接寻址和立即寻址等寻址方式给出,而目的操作数总是在寄存器内。这些指令可完成整数和浮点数高精度运算和处理,有些指令还可完成逻辑运算和处理。TMS320VC33的二操作数指令共35条,表4.2列出了二操作数指令的指令格式、用途、格式操作及其说明等表4.2二操作数指令上述35条指令可以分为下面几个部分:

(1)加法指令:ADDC、ADDF、ADDI;

(2)减法指令:SUBB、SUBC、SUBF、SUBI、SUBRB、SUBRF、SUBRI;

(3)乘法指令:MPYI、MPYF;

(4)逻辑运算指令:AND、ANDN、OR、NOT、XOR;

(5)移位指令:ASH、LSH、ROL、ROLC、ROR、RORC;

(6)比较指令:CMPI、CMPF;

(7)取绝对值指令:ABSI、ABSF;

(8)取反指令:NEGB、NEGF、NEGI;

(9)变换指令:FIX、FLOAT;

(10)其他:NORM、TSTB、RND。

例4.8加法运算。如:ADDIR0,R6指令执行前 指令执行后

R0=123h R0=123h

R6=35h R6=158h例4.9带借位的减法。如:SUBB*AR5++(4),R0指令执行前 指令执行后

R0=124h R0=120h

AR5=809800h AR5=809804h

C=1

C=1

(809800h)=3h

(809800h)=3h

例4.10条件减法。如:SUBC3000,R0指令执行前 指令执行后

R0=7D0h(2000) R0=FA0h例4.11乘法运算。如:MPYIR1,R3指令执行前 指令执行后

R1=5h R1=5h

R3=6h R3=1Eh例4.12逻辑运算。如:ANDN@980Ch,R0指令执行前 指令执行后

R0=7D0h R0=6D0h

DP=80h DP=80h

(80980CHh)=123h (80980CHh)=123h例4.13移位指令。如:ASHR1,R0指令执行前 指令执行后

R1=FFFFFFFBh(-5) R1=FFFFFFFBh(-5)

R0=123h R0=9h例4.14比较指令。如:CMPIR1,R0指令执行前 指令执行后

R0=5h R0=5h

R1=8h R1=8h

N=0

N=1

C=0

C=1例4.15取反指令。如:NEGI200,R0指令执行前 指令执行后

R0=5h R0=FFFFFF38h(-200)4.2.3三操作数指令与二操作数指令不同的是,三操作数指令的源操作数有两个。源操作数的寻址方式既可以是寄存器寻址,也可以是间接寻址,而目的操作数只能通过寄存器寻址得到。对于整数运算来说,寄存器寻址可以利用任意CPU寄存器,而对浮点数来说,只能使用R0~R7。若浮点数采用间接寻址的方式,立即数给出的偏移量只能用0或1,超出范围可用索引寄存器(IR0、IR1)给出。TMS320VC33的三操作数指令一共有17条,内容涉及加法、减法、乘法、逻辑运算、移位以及比较指令等,表4.3列出了三操作数指令的指令格式、用途、格式操作及其说明等。表4.3三操作数指令例4.16三操作数的加法指令。如:ADDC3R7,*AR5++(IR0),R6指令执行前 指令执行后

R7=125h R7=125h

AR5=809800h AR5=809810h

IR0=10 IR0=10

R6=35h R6=626h

C=1 C=1

(809800h)=500h (809800h)=500h例4.17三操作数的算术移位指令。如:ASH3R7,*AR5++(IR0),R6指令执行前 指令执行后

R7=FFFFFFFBh(-5) R7=FFFFFFFBh

AR5=809800h

AR5=809810h

IR0=10

IR0=10

R6=35h

R6=FFFFFFFCh

(809800h)=FFFFFF9Ch (809800h)=FFFFFF9Ch例4.18三操作数的逻辑移位指令。如:LSH3R7,*AR5++(IR0),R6指令执行前 指令执行后

R7=FFFFFFFBh(-5) R7=FFFFFFFBh

AR5=809800h

AR5=809810h

IR0=10

IR0=10

R6=35h

R6=07FFFFFCh

(809800h)=FFFFFF9Ch (809800h)=FFFFFF9Ch4.2.4流程控制指令所谓流程控制指令,是指改变程序运行路径的指令,如块重复、跳转、子程序调用、陷阱和中断等。包括TMS320VC33在内的TMS320C3x和C4x系列的DSP提供了灵活和强大的流程控制指令和控制方法,极大地方便了程序的设计。这些指令的指令格式、用途、格式操作及其说明等如表4.4所示。表4.4流程控制指令续表

1.三种类型的跳转指令

1)标准跳转指令标准跳转指令包括重复、调用、返回和陷阱,遇到标准跳转指令时,程序立即发生转移。例4.19标准跳转指令。如:BR80h指令执行前 指令执行后

PC=123h

PC=80h

2)条件跳转指令条件跳转指令是指当条件满足时可使程序发生转移的指令,而跳转条件是由前一条指令的执行结果决定的,通常比较指令和位测试指令的执行都会影响条件标志位。TM320C3x系列DSP有20个条件代码,可用于任何条件分支指令。这些条件包括有符号数和无符号数与0的比较,这种比较基于各个条件标志的状态。所有无条件指令中都有后缀“U”,以表示无条件跳转。状态寄存器ST中有七个条件标志位,可提供算术和逻辑指令操作结果的有关信息,下面的两个条件之一可对这些标志位产生影响:①目的寄存器是扩展精度寄存器R0~R7之一;②如果指令是比较指令之一(CMPF、CMPF3、CMPI、CMPI3、TSTB、TSTB3),则将根据CPU寄存器的值修改状态寄存器中的标志位。另外,影响条件标志的指令有:比较和位测试等不存储结果的指令,产生了下溢出或上溢出的算术运算指令,以及其它一些需要将结果存储到寄存器中的浮点、整型和逻辑操作指令。除了状态寄存器中的条件标志外,还有一些其它用于跳转或分支指令的条件,这些条件可用于取代流程控制指令中的“cond”,表4.5列出了这些条件所属的类型、采用的助记符、含义及其与状态寄存器ST中标志位的对应关系,表中也包括了状态寄存器中的部分标志位。表中所述的下溢出和上溢出分别指超过了DSP所能表示的最小数和最大数。表4.5用于流程控制的条件标志例4.20条件跳转指令。如:BCR1指令执行前 指令执行后R1=125h R1=125hPC=809800h PC=125hC=1 C=1例4.21条件跳转指令。如:CMPIR1,R2DBGTAR2,R4指令执行前 指令执行后R1=125h R1=125hR2=543h R2=543hAR2=8h AR2=7hR4=897h R4=897hPC=809900h PC=897h例4.22中断返回指令。如:RETIZ指令执行前 指令执行后PC=125h PC=567hSP=809900h SP=8098FFhZ=1 Z=1(809900h)=567h (809900h)=80h

3)延迟跳转指令与前面的指令不同的是,当跳转条件满足时延迟跳转指令并不立即生效,而是在执行完紧跟其后的三条指令后再进行程序的转移。常见的延迟跳转指令有:BcondD、BRD、DBcondD,值得注意的是延迟跳转指令后面的三条指令不能出现跳转、调用、返回、比较、循环等操作。例4.23延迟跳转指令。 指令执行前指令执行后BRD 80h PC=123hPC=124hLDI1,R1 PC=124hPC=125hSTIR1,*AR1 PC=125hPC=126hADDI*AR1,R2 PC=126hPC=80hNOP例4.24不正确的延迟跳转指令。

BZDLOOP1NOPNOPBRLOOP2 ;该指令位置不对,“BZDLOOP1”后三条指令内不能出现跳转指令

NOPNOP

2.子程序调用指令调用和陷阱提供了执行一个子程序或函数的方法。在改变PC的内容之前,CALL、CALLcond和TRAPcond指令先把PC值推入堆栈,在使用RETScond或RETIcond指令时,堆栈可提供返回。CALL占4个指令周期,而CALLcond和TRAPcond占5个指令周期。

(1) CALL指令将下一个PC值推入堆栈并且将src操作数放入PC,其中src是一个24位的立即数。

(2) CALLcond指令与CALL指令类同,但只有当规定的条件为真时才执行,另外,CALLcond指令中的src是PC相对寻址或寄存器寻址方式。

(3) TRAPcond也是一个条件跳转指令,只有当规定的状态为真时才执行,且执行时:①中断被禁止,ST的GIE位写0;②下一个PC值存入堆栈;③从陷阱矢量表的某一个指定单元中检索出相应的向量并且加载到PC中。这个特殊地址由指令中的陷阱数值来确认。从功能上讲,调用和陷阱完成相同的功能(即一个子函数被调用或执行,然后返回调用函数),只是陷阱的优点在于,当执行陷阱子程序时中断被自动禁止,而且可以使用陷阱间接地调用函数。例4.25子程序调用。

AA:LDI3H,R1

LDI3H,R4

CALLAA

指令执行前 指令执行后

PC=809800h

PC=809801h PC=809801h

PC=809802h

PC=809802h PC=809800h

SP=7h SP=8h

(8h)=809803h例4.26条件陷阱。如:TRAPC5指令执行前 指令执行后

PC=125h PC=18h

SP=809900h SP=809901h

C=1 C=0陷阱矢量表5对应的向量=18h (809901h)=126h

3.重复操作指令重复方式包括单条指令的重复执行和一段程序的重复执行,这些指令对实现无开销的循环特别重要,同时也简化了编程。利用重复方式能够以尽可能短的时间来执行程序代码。

TMS320C3x的重复方式允许实现过零循环。TMS320C3x提供了两条支持过零循环的指令:块重复指令RPTB和单条语句的重复指令RPTS。RPTB允许一个程序块被重复执行规定的次数;RPTS允许对单条指令重复执行规定的次数,并且只需一次取指,这就有效地减少了总线的拥挤。用于重复控制的寄存器有三个,分别是重复起始地址寄存器RS、重复结束地址寄存器RE和重复计数寄存器RC,它们都是CPU寄存器。

1)重复方式初始化状态寄存器中的重复方式标志位RM对于RPTB和RPTS的操作是非常重要的。如果RM=0,则不进行重复取指;如果RM=1,则进行重复取指。另外,需要说明的是,状态寄存器中还有一个标志位S,S位对用户是隐含的,不能被编程,但对充分描述RPTB和RPTS的操作是必要的。如果RM=1且S=0,则执行的是RPTB,程序从存储器中取指;如果S=1和RM=1,则执行的是RPTS,第一次从存储器中取指,以后从寄存器中取指。重复方式的正确操作需要正确地初始化以上所有寄存器和状态寄存器。

RPTB初始化:当执行指令RPTBsrc时,CPU按以下步骤操作:

(1) PC+1→RS,将程序块的起始地址装入RS;

(2) src→RE,将src装入RE(程序块的结束地址),其中src含有24位地址值;

(3) 1→RM,表示是重复操作方式;

(4) 0→S位,表明这是块重复操作方式。程序块的重复执行次数是通过初始化RC寄存器来确定的。由于RPTB的执行并不装载PC,该寄存器必须由用户明确地装载。典型的块重复操作过程如下:

LDI15,PC ;15→RC

RPTBLOOP ;LOOP→RE,PC+1→RS,1→RM,0→S在典型应用中,重复方式至少要对一个程序块重复执行一次,重复计数器由块重复次数减1来装载,所有由RPTB初始化的块重复均可被中断,即在块重复过程中,可以响应中断请求。

RPTS初始化:当执行指令RPTSsrc时,对紧跟其后的指令重复执行src+1次,src的含义见表4.4。执行RPTS指令时,CPU按以下步骤操作:

(1) PC+1→RS,将起始地址装入RS;

(2) PC+1→RE,将程序的结束地址装入RE。由于这是一条单指令的重复,起始地址和结束地址是相同的;

(3) 1→RM,设置状态寄存器用来指示操作的重复方式;

(4) 1→S位,表明这是单条指令的重复操作方式;

(5) src→RC,将操作数src装入RC。被RPTS初始化的单条指令的重复是不可中断的,因为RPTS仅对指令字取指一次,若再将指令字保持在指令寄存器中以备后用,则中断会导致指令字丢失。如果某条单指令必须是可重复的或可中断的,则应当对这条单指令使用RPTB指令。

2)重复方式的操作过程在重复方式下,CPU要比较寄存器RE和程序计数器PC的内容,如果它们相匹配并且重复计数器非负,则重复计数器递减,并且继续进行处理。注意:重复计数器中装载的值应比重复执行的次数少1,比如RC=4,那么重复执行的次数为5次。调整PC的详细算法如下所述。注意:①当RC=080000000h时,产生重复的最大值,这将导致080000001h次重复;当RC=0时,产生最小重复,仅有一次;②应满足:RE≥RS,否则代码不会被重复,甚至RM仍然保持为1;③当写0到重复计数器或状态寄存器的RM位时,可以停止未执行完的重复。例4.27RPTB操作。

LDI15,RC ;将15装入重复计数器

RPTBENDLOOP ;重复执行下一条指令到ENDLOP之间的程序块,共重复16次

STLOOP ;ENDLOOP和STLOOP为标号

…ENDLOOP由于块重复过程中需要修改程序计数器,所以其它指令就不能同时修改程序计数器。必须遵循的两条规则是:①程序块中的最后一条指令不能是Bcond、BR、Bdcond、CALL、CALLcond、TRAPcond、RETIcond、RETScond、IDLE、RPTB或RPTS;②从程序块中的最后四条指令中的任何一条指令不能是BcondD、BRD或DBcondD。如果不符合这两条规则中的任何一条,PC值就将成为不确定的。例4.28块重复中,跳转指令的位置不正确。

LDI 15,RC ;程序计数器装载15

RPTB ENDLOOP ;执行程序块

STLOOP: ;从RTLOOP到

ENDLOOP重复执行16次

ENDLOOP:BRLOOPS ;与规则①冲突例4.29块重复中,延迟跳转指令的位置不正确。

LDI15,RC ;程序计数器装载15

RPTBENDLOOP ;执行程序块

STLOOP:… ;从RTLOOP到ENDLOOP重复执行16次

BRDLOOPS;与规则②冲突

ADDF

MPYF

ENDLOOP:SUBF

RPTB是可以嵌套的,由于所有的控制是通过RS、RE、RC和ST寄存器定义的,保留和恢复这些寄存器要考虑到它们的嵌套。状态寄存器中的RM位可以用来确定块重复方式是否有效。例如,如果中断服务子程序需要使用RPTB,则在另一个块重复期间有可能发生中断,当响应中断后,这个中断服务子程序首先检测RM位。如果该位被置位,中断服务子程序保留RS、RE、RC和ST,然后执行中断服务子程序中的块重复。在返回中断服务子程序之前,恢复RS、RE、RC和ST。如果没有对RM置位,就没有必要保留和恢复这些寄存器。

4.中断

TMS320C3x支持多个内部和外部中断,内部中断由DMA控制器、定时器和串行口产生,外部中断由4个外部中断引脚~上的触发信号产生,这种触发信号包括电平触发和下降沿触发。外部中断采用电平触发方式时,低电平的持续时间至少要持续一个H1或H3周期,但不能超过2个H1或H3周期,否则会有多个中断被确认。如果多个中断在一个时钟周期内同时发生,则按照~的优先级顺序执行。DSP响应中断后,状态寄存器ST中的GIE被复位为0,使以后的中断无效,直到GIE再次被置为1。对于采用下降沿触发的中断,外部管脚必须从1变为0,并且至少要保持一个H1或H3周期。与中断有关的寄存器包括状态寄存器ST、中断使能寄存器IE和中断标志寄存器IF。ST中的CPU全局中断使能标志位GIE控制所有的CPU中断,当GIE=1时,CPU响应中断;GIE=0时,CPU则不响应。当外部中断发生时,IF寄存器中相应的标志位被设置为1,当中断被CPU或DMA响应后,相应的中断标志位被内部中断回答信号清零。但当中断为电平触发方式时应当注意到,如果中断回答信号出现后仍然是低电平,则中断标志位将只被清零一个周期后又被置位,这就会被误认为又发生了一次中断。用软件可以对中断标志寄存器IF进行读或写。向IF寄存器写入1就把相应的中断标志置位为1,同样,写入0就把相应的中断标志位复位为0。所以,通过软件就可触发或消除所有的中断。

内部中断的操作方式与外部中断相类似,不过所有的内部中断请求信号的持续时间由硬件自动保证为一个H1/H3周期。

TMS320C3x允许CPU和DMA并行对中断做出反应和处理,发生CPU中断至少需要满足下列2个条件:

(1)通过设置状态寄存器的GIE控制位为1,以允许CPU中断;

(2)设置IE寄存器中相应的控制位,以便允许某一具体的中断发生,而且IF寄存器中相应的控制位为1。

CPU对中断的响应过程是:

(1) IF寄存器中相应的标志位和ST寄存器中的GIE被清零;

(2) CPU处理已经被取指的指令;

(3)当前的PC值推入栈顶;

(4)取中断向量并装入PC;

(5)开始执行中断服务子程序的第一条指令。如果希望中断服务子程序可被中断,可以在进入中断服务子程序后设置GIE=1。需要注意的是:①在执行指令RPTS的过程中不响应中断;②在执行完紧跟在延迟跳转指令后面的3条指令之前,不响应中断;③已经完成了取指而处于译码、读操作数和执行阶段的所有指令将被执行完后才能响应中断;④正处于取指阶段的指令将被停止取指。

CPU全局中断是否允许是由ST寄存器中的GIE位控制的,而所有的DMA中断都是由IE寄存器的高16位和DMA全局控制寄存器中的SYNC位控制的。TMS320C3x允许CPU和DMA并行响应和处理中断,DMA的中断过程与CPU的中断过程类似,图4.1给出了CPU和DMA的中断处理流程图。图4.1CPU和DMA中断处理示意图4.2.5互锁指令

互锁操作指令支持多处理器之间的通信,可有效保证信号的同步,实现多个DSP之间的高速通信和高速信号处理。这些指令的指令格式、用途、格式操作及其说明如表4.6所示。表4.6互锁操作指令

例4.30互锁指令。

如:LDP80  ;装入数据页指针

LDII

@9800h,R1

;互锁操作开始,将地址为809800h单元中的数值放入R1中

STIIR2,@9900h ;互锁操作结束,将R2中的数值放入地址为809900h的单元中4.2.6并行指令

并行操作指令具有高度的并行操作能力,在一个指令周期内可以同时完成两条指令的处理,但并不是任何两条指令都可以实现并行操作,可以并行处理的指令局限于以下类型:

(1)算术运算或逻辑运算指令与存储指令的并行,如表4.7中的第1~16行;

(2)两条寄存器装载指令的并行,如表4.7中的第17~18行;

(3)两条算术运算指令的并行,如表4.7中的第19~24行;

(4)两条存储指令的并行,如表4.7中的第25~26行;

(5)寄存器装载和存储指令的并行,如表4.7中的第27行。这里所述的寄存器装载指令是指LDI和LDF,它们的目的地址指向寄存器;存储指令指STI和STF,它们的目的地址指向存储器。

在并行寻址中,操作数的寻址方式只有间接寻址和寄存器寻址两类,其中间接寻址的偏移量取值只限0或1,超出范围用索引寄存器(IR0、IR1)表示,而寄存器的操作仅对R0~R7有效。

成对指令中的第一条指令以独立的源语句输入,第二条指令前必须加上两条垂直线“||”。表4.7列出了并行指令的指令格式、格式操作及其说明。表4.7并行运行指令

续表例4.31取绝对值与存储指令的并行。

如:ABSI*-AR5(1),R5

||STIR1,*AR1--(IR1)

指令执行前 指令执行后

R1=12h R1=12h

R5=54h R5=5h

AR1=809802h AR1=809800h

AR5=809901h AR5=809901h

IR1=2h

IR1=2h

(809900h)=FFFFFFFBh(-5) (809900h)=FFFFFFFBh

(809802h)=28h (809802h)=12h例4.32算术运算与存储指令的并行。

如:ADDI3*--AR5(IR0),R3,R5

||STIR1,*AR1

指令执行前 指令执行后

R1=12h R1=12h

R3=9h

R3=9h

R5=54h

R5=4h

AR1=809802h AR1=809802h

AR5=809901h AR5=809800h

IR0=1h

IR0=2h

(809900h)=FFFFFFFBh(-5) (809900h)=FFFFFFFBh

(809802h)=28h (809802h)=12h例4.33逻辑运算与存储指令的并行。

如:AND3*+AR1(IR0),R4,R7

||STIR1,*AR2

指令执行前 指令执行后

R1=12h R1=12h

R4=10h R4=10h

R7=54h R7=0h

AR1=809802h

AR1=809802h

AR2=809901h

AR2=809901h

IR0=1h IR0=1h

(809803h)=101h

(809803h)=101h

(809901h)=18h

(809901h)=12h例4.34移位指令与存储指令的并行。

如:LSH3R1,*+AR1(IR0),R2

||STIR3,*AR2

指令执行前 指令执行后

R1=10h R1=10h

R2=56h R2=0AC0000h

R3=9h R3=9h

AR1=809802h AR1=809802h

AR2=809901h AR2=809901h

IR0=1h IR0=1h

(809803h)=0ACh

(809803h)=0ACh

(809901h)=18h

(809901h)=9h

例4.35两条算术指令的并行。

如:MPYI3R0,R5,R1

||ADDI3*AR2,*AR1--(IR1),R2

指令执行前 指令执行后

R0=2h R0=2h

R1=5h R1=0Ah

R2=9h R2=656h

R5=5h R5=5h

IR1=2h IR1=2h

AR1=809907h AR1=809805h

AR2=809901h AR2=809901h

(809901h)=123h (809802h)=123h

(809907h)=533h (809901h)=533h例4.36逻辑运算与存储指令的并行。

如:NEGI*-AR1,R1

||STIR2,*AR2++(IR0)

指令执行前 指令执行后

R1=2h R1=FFFFFF9Ch(-100)

R2=5h R2=5h

IR0=3h IR0=3h

AR1=809806h

AR1=809806h

AR2=809900h

AR2=809903h

(809805h)=100h

(809805h)=100h

(809900h)=456h

(809900h)=5h例4.37逻辑运算与存储指令的并行。

如:OR3*++AR1,R1,R2

||STIR3,*AR2

指令执行前 指令执行后

R1=2h R1=2h

R2=5h R2=12h

R3=9h R3=9h

AR1=809800h AR1=809801h

AR2=809900h AR2=809900h

(809801h)=10h (809801h)=10h

(809900h)=456h (809900h)=9h例4.38寄存器装载指令的并行。

如:LDI*++AR1,R1

||LDI*AR2,R2

指令执行前 指令执行后

R1=2h R1=10h

R2=5h R2=456h

AR1=809800h AR1=809801h

AR2=809900h AR2=809900h

(809801h)=10h (809801h)=10h

(809900h)=456h (809900h)=456h例4.39存储指令的并行。

如:STIR1,*-AR1(IR0)

||STIR2,*AR2

指令执行前 指令执行后

R1=2h R1=2h

R2=5h R2=5h

IR0=5h IR0=5h

AR1=809800h AR1=809800h

AR2=809900h AR2=809900h

(8097FBh)=10h (8097FBh)=2h

(809900h)=456h (809900h)=5h4.3公共目标文件格式

汇编器和链接器建立的目标文件格式称为公共目标文件格式(CommonObjectFileFormat,COFF),采用这种目标文件格式更有利于模块化编程,应用COFF编写程序时不必为程序代码和变量指定地址,这给程序的编写和移植带来极大的好处。在实际操作时,通过建立命令文件,实现对存储器的资源和代码段的管理。4.3.1汇编器的作用

汇编器的作用就是将汇编语言源程序转换成机器语言目标文件。这些目标文件都是公共目标文件格式(CommonObjectFileFormat,COFF),其主要功能如下:

(1)将汇编语言源程序汇编成一个可重新定位的目标文件(扩展名为 .obj);

(2)如果需要,则可以生成一个列表文件(扩展名为 .lst);

(3)将程序代码分成若干个段,每个段的目标代码都有一个SPC(段程序计数器)管理;

(4)定义和引用全局符号,需要的话还可以在列表文件后面附加一张交叉引用表;

(5)对条件程序块进行汇编;

(6)支持宏功能,允许定义宏命令。4.3.2链接器的作用链接器的主要任务是:根据链接命令文件或命令文件( .cmd文件),将一个或多个COFF目标文件链接起来,生成存储器映射文件( .map)和可执行的输出文件(.out文件)。在链接过程中,链接器将各个目标文件合并起来,并完成以下工作:

(1)将各个段配置到目标系统的存储器;

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

(3)解决输入文件之间未定义的外部引用。4.3.3公共目标文件格式的相关概念

用户使用公共目标文件格式编写程序时,多采用代码段和数据段的概念,这种段称为section。段就是指在存储器中占据连续空间的代码块或数据块,它是目标文件中的最小单位,有些资料中也将段称为“块”。所有的COFF目标文件都包括下面形式的段,其中前3个段为COFF目标文件最基本的段。

(1) .text:用以定义可执行代码段。

(2) .data:用以定义初始化数据段。

(3) .bss:为未初始化的数据保留空间,未初始化的数据指运行过程中的变量,在定义时无具体内容,仅仅是为其预留一定的空间。

(4) .sect:用以定义已初始化且有名称的段,该段中可以含有代码或数据,用于创建自定义段。当程序员想把一部分程序放在不同于.text的存储器中时,需使用该命令,对数据也可进行同样处理。

(5) .usect:为未初始化且有名称的段保留空间,与 .bss类同,但被保留的空间可以是不连续的。

(6) .asect:用于建立具有绝对地址的有名称的初始化段。上述6种段从是否初始化的角度来看,可以划分为已初始化段和未初始化段。其中 .text、.data、.sect、.asect创建的都是已初始化的段,.bss、.usect创建的段属于未初始化的段。未初始化的段在定义时没有具体内容,已初始化的段是有具体内容的,例如 .text段含有源程序代码,.data段是由具体数据或常数组成的。未初始化段主要用来为DSP在存储器中保留空间,这些段中没有实际的内容,仅仅是保留空间,程序可以在运行时利用这些空间来建立和保存变量,它们一般被分配到RAM中。建立未初始化段的命令有 .bss和 .usect。汇编器提供了若干将各种代码和数据段与相应的段联系的命令,汇编器是在汇编过程中建立这些段的。图4.2给出了一个包含 .text、.data和 .bss段的目标文件。图4.2段在存储器中的分配情况链接器的一个主要功能是将段定位至目标存储器中。在汇编器汇编形成的目标文件中,除了用 .asect命令定义的段之外,其他程序段和数据段的地址都是不确定的。确定段地址的工作一般由链接器来完成。由于大部分系统一般含有多个类型的存储器(EPROM、RAM或FLASH等),采用段可以使用户更有效地利用目标存储器。所有的段都可以独立地进行重定位,因此可以将不同的段分配到各种存储器中。例如,可以定义一个包含已初始化的段,然后将它分配至包含EPROM的存储器映射中。图4.2也示出了目标文件中的段和目标系统中的存储器之间的关系。4.3.4汇编器对段的处理

汇编器对段的处理功能主要是确定汇编语言程序各部分属于哪个特定的段。汇编器有六个命令,即 .bss、.usect.、text、.data、.sect和 .asect,其中,.bss和 .usect命令创建的段属于未初始化的段,.text、.data、.sect和 .asect命令则是建立已初始化段。当然,如果在程序中未用任何命令来定义,那么汇编器将把所有的程序段或数据段统一汇编至 .text中。

1.未初始化段命令

(1) .bss命令的用途是为变量保留空间,格式是:

.bss符号,字数上述命令格式中的“符号”和“字数”都是不可省略的参数。符号由程序员自己定义,如“var1”、“var2”等,符号指向被保留空间中的第一个字,字数则以数字的形式指定需要保留几个字。

例:.bssarray,100;该命令为变量array分配了100个字

(2) .usect命令的格式如下:

符号.usect“段名”,字数

“符号”、“段名”和“字数”都是不可省略的参数,其中“段名”要用双引号括起来,“字数”则用数字表示需要保留的字的数目。“符号”和“段名”都是程序员自己定义的,但“段名”的长度不能超过8个英文字符。该命令与 .bss类似,都是为变量保留空间,该空间内事先无任何内容,只是为程序运行过程中产生的变量预留了空间,但它们也有区别。如果在程序中出现了多个 .bss命令,不管该命令中的符号是否相同,汇编器都将各个 .bss命令预留的空间统一汇编到一个段中;但如果出现了多个 .usect命令,则要看其名称是否一致,只有该命令中指定的“段名”相同时,才汇编到一个段中,否则,不同段名指定的空间将汇编到不同的段。

例4.40用 .usect建立不同的段。1 .text ;text段开始

2 LDIR0,R1 ;在text段中

3 ptr .usect"var1",1

4 array .usect"var1",100

5 LDIR1,R2 ;仍在text段

6 dflag .usect"var1",50

7 LDIR2,R3 ;仍在text段

8 .bssbuffer1,1

9 .bssbuffer2,10

10 vec .usect"var2",100

11 LDI@vec,R0 ;仍在text段对上述程序汇编后,共产生4个段:

①.text:包含第2、5、7、11行等4行指令的目标代码。

②.bss:在存储器中保留了11个字,包括第8行定义的1个字和第9行定义的10个字,其中buffer1和buffer2分别指向上述两个字块的第一个字。

③var1:在存储器中为该段保留了151个字,包括第3行定义的1个字,第4行定义的100个字和第6行定义的50个字,其中符号ptr、array和dflag分别指向上述3个字块的第一个字。

④var2:在存储器中保留了100个字,vec指向第一个字。本例中 .text为初始化的段,其它三个为未初始化的段。汇编器在遇到 .text、.data、.sect、

.asect等初始化的段时,立即停止汇编至当前段并开始所遇到的新段的汇编,但当遇到 .bss、.usect时并不结束当前段的汇编,而只是暂时离开当前段,所以 .bss和 .usect命令可以出现在已初始化段中的任何地方,而不影响已初始化段的内容。

2.已初始化段命令

.text、.data、.sect、.asect命令建立的段为已初始化的段,已初始化段包括可执行代码和已初始化的数据,这些段的内容存储在目标文件中。当程序装入时,存放在存储器中。它们的功能分别如下:

(1) .text命令。此命令没有任何参数,在汇编语言编制的源程序中单独占一行。“text”本身就是段名,该段中含有可执行代码,它告诉汇编器将 .text下面的源代码汇编到text段。汇编器可以把所有段名相同但分布在程序多处的数据或程序汇编到一个段中,完成这一有序工作的是段程序计数器(SectionProgramCounter,SPC)。初始化时,所有的SPC均置0,随着数据或程序在段中的放置,计数器的值发生变化。在将下一段具有相同段名的可执行代码或数据汇编至同一段中之前,先取出相应段的SPC,随着数据或程序地加入,SPC值发生变化。如果该段的内容原来为空,则SPC从零开始计数;如果该段的内容不为空,则SPC接着原来的计数值继续计数,即每汇编到该段一个字,计数值加1。正是由于上述原因,.text等创建初始化段的命令可以在一个程序中出现多次。需要说明的是,汇编器总是假定.text是缺省的段,因此,如果在程序的开始没有指定 .data、.sect或 .asect等初始化的段,汇编器将自动地将所遇到的代码汇编到 .text段。

(2) .data命令。该命令没有任何参数,在程序中单独占一行,“data”本身就是段名。该命令告知汇编器将 .data下面的源代码汇编到data段,直到遇到其它已初始化的段时才停止当前段的汇编。data段一般含有 .word、.byte、.float等对常数进行初始化的命令。例4.41.data命令及用于常数初始化的常用命令。

1.data

2coff.word011h,022h,808060h

3val.word-123h

4const.byte0FCh,080h

5pai.float3.141596

6.text

7LDIR0,R2

8.end该例中coff、val、const、pai等为符号,命令后面的数据可以是一个也可以是多个。汇编后,上述符号都有一个地址,它们分别指向相应命令后面的第一个数。上述3个用于定义常数的命令的区别是:

.word定义32位的整型数

.byte定义8位的整型数

.float定义32位的单精度浮点数

该例中.end是程序的结束命令,当汇编器遇到该命令后,停止汇编。另外两个命令建立的段为用户自定义的段命令,其中 .asect命令建立的段具有绝对的地址,一般不建议使用。当汇编器遇到 .text或 .data或 .sect命令时,它将停止对当前段的汇编,然后将紧接着的程序代码或数据汇编到指定的段中,直到在遇到另一条 .text、.data、.asect或 .sect命令为止。

3.自定义的段命令

自定义的段就是程序员自己建立的段。有三条命令用来建立自定义的段:.usect、.sect和 .asect。其中,.usect命令前已讲及,不再赘述。

(1) .sect命令的常用格式为

.sect“段名”

该命令中的段名是程序员自己定义的名称,用双引号括起来,字符长度不能超过8个字符。汇编器遇到该命令时,开始将其后的源代码汇编到所定义的段名中。该段中或者含有可执行的程序,类似于text段,或者含有数据,类似于data段。除了有一个专门的名称外,该命令的用法也与 .text和 .data相类似,利用这个专门定义的名称,程序员可以将一部分程序或数据放在不同于 .text和 .data的段中,即可以利用该命令建立自己定义的段。

(2) .asect命令与 .sect命令类似,也是创建一个有名称的段,但在段名后需要用数值给出该段在存储器中的绝对地址。由于这种作法不利于程序的可移植性,所以很少使用 .asect命令。其格式为:

asect"段名",地址4.3.5链接器对段的处理

链接器对段的处理主要有两个功能:首先它将COFF目标文件中的段组合起来,建立可执行的COFF输出模块;其次链接器还为输出段选择存储器地址。

为了完成上述功能,链接器有MEMORY和SECTIONS两条命令。MEMORY用于定义目标系统的存储器,可以定义每一段存储器的起始地址和长度;SECTIONS用于累加器如何组合输入段以及将输出段放至何处。这两条命令并不是非用不可。如果不用,链接器将采用缺省分配算法为各个段分配空间;如果使用,那么需要将这些命令放在命令文件(*.CMD文件)中。

1.缺省分配算法

如果不给链接器提供命令文件,那么链接器将用缺省的算法。缺省分配算法如下:

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

(2)假定全部的存储器空间都用来分配目标代码;

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

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

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

(6)将自定义的段分配到紧接着 .bss的存储器中。若自定义段多于一个,则按自定义段在文件中的先后顺序存放。需要注意的是,链接器只是为各段指定了地址而不将程序装入实际的存储器。这一工作由引导程序来完成。如果输入的目标文件有多个,则链接器首先将各个文件中相同段名的段组合起来,形成相应的输出段,然后再按上述方法分配存储器。

2.用命令文件分配存储器

缺省分配文件将段分配到存储器中时,必须按缺省分配算法进行。但在实际的应用中,许多情况并不一定能够满足缺省算法的要求,DSP的硬件系统中可能包含多种类型的存储器,如SRAM、SDRAM、DRAM、ROM、EPROM、FLASH等,用户可能将不同的段分布于不同的内存,这时就不能采用缺省算法,必须建立一个命令文件,在命令文件中用MEMORY和SECTIONS命令将各段分配至相应的存储器中。例4.42命令文件的实例。

MEMORY

{

RAM0:origin=809800h length=400h

RAM1:origin=809c00h length=300h

RAM2:origin=800000h length=4000h

RAM3:origin=804000h length=4000h

}SECTIONS

{

.text: LOAD=RAM2

.data: LOAD=RAM3

.bss: LOAD=RAM0

.var: LOAD=RAM1

}该例通过MEMORY命令定义了RAM0、RAM1、RAM1和RAM3等4个RAM块的起始地址和长度,它们的起始地址必须在第2章图2.8(b)所示RAM的允许范围内,其长度不能超过实际允许的空间。SECTIONS命令将 .text、.data、.bss、.var等4个段分配到有关的RAM中,其中 .var是程序员通过 .sect或 .usect自定义的段

3.程序重定位

汇编器对每一个段进行汇编时,都假设起始地址为0。每一个段中所有的重定位符号(标号)都是相对于0地址而言的。但实际上并不是所有的段都是以0地址作为起始地址的。因此链接器必须通过下面的步骤对每个段进行重定位。

(1)将段分配到存储器,使其有合适的起始地址;

(2)调整符号值,使之与新的段地址相适应;

(3)调整重定位后符号的参考值,使之与调整后的符号值相一致。链接器利用重定位符号来调整符号的参考值,每次当一个重定位符号被参考时,汇编器就建立一个重定位项。利用这些重定位项,链接器在符号被重定位之后修改参考值。例4.43产生重定位项的代码(TMS320C3x)。

1 .refX

200000000 .text

30000000060000000! BRX;产生一个重定位项

40000000108200002 LDI@Y,R0;产生一个重定位项

500000002060000000Y:IDLE该例中,符号X和Y都是可重定位的,X在其它模块中定义,Y在本模块的.text块中定义。汇编之后,X的值为0(汇编器假定所有未定义的外部符号的值为0),而Y的值为2(相对于 .text块的0地址)。汇编器为X和Y各产生一个重定位项。X的参考是外部参考(在列表中用!表示),Y的参考是内部定义的可重定位符号(用@表示)。链接之后,假定X重定位至地址100h,且.text块重定位到起始地址200h,则Y重定位后的值为202h。链接器利用这两个重定位项在目标代码中补上这两个参考:

60000100 BRX ;变为60000100

08200002LDI@Y,R0 ;变为08200002

COFF的目标文件中的每一块都有一个重定位项目表,表中包含了块中每一个可重定位参考的一个重定位项。链接器通常在使用过重定位项之后就将它去除,以防止对输出块再次重定位(如果目标文件被重新链接或被装入)。没有重定位项的文件就是所有地址都是绝对地址的绝对文件,如果程序员要保留重定位项,激活链接器的 -r选项即可。有时候某块程序装入到某个存储器中但需在另一块存储器中运行,比如一个程序中的关键代码装在ROM中但需在更高速度的RAM中运行时就是如此,此时必须进行运行时的重定位。实现的方法很简单,可在链接器的命令文件的SECTIONS中将块分配两次,一次设定装入地址,另一次则设定运行地址。例如:

.text:LOAD=ROM,RUN=RAM0

4.COFF文件中的符号

COFF文件包含一个与程序中的符号信息有关的符号表,链接器在进行重定位时要用到这个表,调试工具也可利用这个符号表提供符号级调试。在一个模块中定义而在另一个模块中引用的符号称外部符号,一般可用 .global命令来标明某一符号。在一个源模块中,外部符号可以是参考(ref)或是定义(ref)。

定义(ref):在当前模块中定义,在其它模块中引用。

参考(ref):在其它模块中定义,在当前模块中引用。下面的代码可说明这两种定义:

.globalX;X在当前模块中定义,在其它模块中引用

.globalY;X在其它模块中定义,在当前模块中引用

X: LDIR0,R1;定义X

LDI@Y,R0 ;引用Y

X是一个在本模块中定义的外部符号,可以在其它模块中引用;Y在其它模块中定义,在本模块中引用。汇编器将X和Y都放在目标文件的符号表中。汇编器汇编使所有的引用与相应的定义相一致,否则将输出一个错误信息,只有没有出错信息才能产生可执行的目标文件。

汇编器并不对其它类型的符号产生符号表项目,因为链接器不需要它们。比如程序标号就不包含在符号表中,除非用 .global来说明。在对程序进行符号级调试时,有时候在符号表中包含程序中的每一个符号,这往往是很有用的,这时需在汇编时激活-s选项。

5.COFF编程举例

本节通过一个TMS320C3x的汇编语言程序来说明基于COFF的汇编语言编程。

例4.44COFF的汇编编程(TMS320C3x)。

.text ;汇编至 .text块

add: LDI10,AR1

LDI0,R1

aloop: ADDI*AR0++,R1

DBNZAR1,aloop

STIR1,@varl

.data ;汇编至 .data块

ivals .word0AAh,0BBh,0CChvar2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论