版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章TMS320C54x汇编语言程序设计内容提要汇编语言程序设计是应用软件设计的基础,主要任务是利用汇编指令和伪指令编写源程序以完成指定的功能。本章将结合例子介绍TMS320C54x汇编语言源程序设计的基本方法,涉及的内容包括:汇编语言源程序的格式常数、字符串、符号和表达式的规定堆栈的使用方法分支、调用、返回控制程序加法、乘法、除法、长字和并行运算程序单指令、块重复、循环嵌套等重复操作程序数据块传送程序小数运算程序和浮点运算程序5.1概述TMS320C54x汇编语言源程序由源语句组成。这些语句可以包含汇编语言指令、汇编伪指令和注释。程序的编写必须符合一定的格式,以便汇编器将源文件转换成机器语言的目标文件。本节将介绍汇编语言源程序的格式、各种常数、符号、字符串和表达式的规定。汇编语言程序以.asm为扩展名,可以用任意的编辑器编写源文件。一条语句占源程序的一行,长度可以是源文件编辑器格式允许的长度,但汇编器每行最多读200个字符。因此,语句的执行部分必须限制在200个字符以内。5.1.1汇编语言源程序格式1.源文件格式助记符指令源语句的每一行通常包含4个部分:标号区、助记符区、操作数区和注释区。助记符指令语法格式:[标号][:]助记符[操作数][;注释]【例5.1.1】助记符指令源语句举例。语句的书写规则:①所有语句必须以标号、空格、星号或分号(*或;)开始;②标号是可选项,若使用标号,则标号必须从第一列开始;③所有包含有汇编伪指令的语句必须在一行完成指定;④各部分之间必须用空格分开,Tab字符与空格等效;⑤程序中注释是可选项。如果注释在第一列开始时,前面必须标上星号或分号,在其他列开始的注释前面必须以分号开头;⑥如果源程序很长,需要书写若干行,可以在前一行用反斜杠字符(\)结束,余下部分接着在下一行继续书写。2.标号所有汇编指令和大多数汇编伪指令都可以选用标号,供本程序或其它程序调用。①标号必须从语句的第1列写起,其后的冒号“:”可任选;②标号为任选项,若不使用标号,则语句的第一列必须是空格、星号或分号;③标号是由字母、数字以及下划线和美元符号等组成,最多可达32个字符;④标号分大小写,且第一个字符不能是数字。在使用标号时,标号的值是段程序计数器SPC的当前值。例如,若使用.word伪指令初始化几个字,则标号将指到第一个字。【例5.1.2】标号格式举例。……9000000;假设汇编了某个其他代码10000040000AStart:.word0Ah,3,70000410003└──标号,值为40h00004200073.助记符助记符用来表示指令所完成的操作,可以是汇编语言指令、汇编伪指令、宏伪指令。助记符指令:一般用大写,不能从第一列开始;汇编伪指令:用来为程序提供数据和控制汇编进程。以句号“.”开始,且用小写;宏伪指令:用来定义一段程序,以便宏调用来调用这段程序。以句号“.”开始,且用小写;宏调用:用来调用由宏伪指令定义的程序段。4.操作数操作数是指指令中参与操作的数值或汇编伪指令定义的内容,紧跟在助记符的后面,由一个或多个空格分开。操作数之间必须用逗号“,”分隔;操作数可以是常数、符号或表达式;操作数中的常数、符号或表达式可用来作为地址、立即数或间接地址;(1)指令的操作数前缀汇编器允许指定的常数、符号或表达式作为地址、立即数或间接地址。作为操作数的前缀有三种情况:使用“#”符号作为操作数的前缀;使用“*”符号作为操作数的前缀;使用“@”符号作为操作数的前缀。①用“#”作前缀使用“#”号作为前缀,汇编器将操作数作为立即数处理。即使操作数是寄存器或地址,也将作为立即数。如果操作数是地址,汇编器将把地址处理为一个数值,而不使用地址的内容。例如:Label:ADD#99,B操作数#99是一个立即数。②用“*”作前缀使用“*”符号作为前缀,汇编器将操作数作为间接地址,即把操作数的内容作为地址。例如:Label:LD*AR3,B操作数*AR3指定一个间接地址。该指令将引导汇编器找到寄存器AR3的内容作为地址,然后将该地址中的内容装入指定的累加器B中。③用“@”作前缀使用“@”符号作为前缀,汇编器将操作数作为直接地址,即操作数由直接地址码赋值。例如:Label:LD@x,A只要DP=0,将直接地址x中的内容装入指定的累加器A中。4.操作数(2)伪指令的立即数将“#”加在数值之前而构成的立即数方式,主要用在指令中。例如:SUB#18,B;操作数#18为立即数通常,立即数在伪指令中用的较少,但在某些情况下,立即数也可以作为伪指令的操作数。例如:.byte18立即数方式没有使用,但汇编器认为操作数是一个数值18(即立即数),用18数值初始化一个字节。5.注释用来说明指令功能的文字,便于用户阅读。注释可位于句首或句尾,位于句首时,以“*”或“;”开始,位于句尾时,以分号“;”开始。注释可单独一行或数行;注释是任选项。例如:1100000.bsssym,;保留空间于.bss***************************************改变段,允许第五个‘mylab’定义***************************************5.1.2汇编语言中的常数与字符串汇编器可支持7种类型的常数(常量)。数据类型举例说明二进制1110001b或1110001B
八进制226q或572Q
十进制1234或+1234或-11234缺省型十六进制0A40h或0A40H或0xA40
浮点数1.623e-23仅用于C语言字符‘D’
字符串“thisisastring”
1.二进制整数二进制整型常量最多由16位二进制数字(0或1)组成,后缀为B(或b)。如果数字小于16位,汇编器将其右边对齐,并在前面补零。例如:10001000B136(十进制)或88(十六进制)0111100b60(十进制)或3C(十六进制)10b2(十进制)或2(十六进制)10001111B143(十进制)或8F(十六进制)2.八进制整数八进制整型常量最多由6位的八进制数字(0到7)组成,后缀为Q(或q)或前缀为0(零)。例如:100011Q32777(十进制)或8009(十六进制)124q84(十进制)或54(十六进制)八进制常数也可使用C语言的记号,即加前缀0。010001132777(十进制)或8009(十六进制)012484(十进制)或54(十六进制)3.十进制整数十进制整型常量由十进制数字串组成,无后缀。取值范围为:-32768~32767或0~65535。例如:21182118(十进制)或846(十六进制)6553565535(十进制)或0FFFF(十六进制)-32768-32768(十进制)或8000(十六进制)4.十六进制整数十六进制整型常量最多由4位十六进制数字组成,带后缀H(或h)。它必须以数字(0~9)开始,也可以加前缀0x。例如:0DH14(十进制)或000D(十六进制)12BCH4796(十进制)或12BC(十六进制)十六进制常数也可用C语言记号,即加前缀0x。0x0D14(十进制)或000D(十六进制)0x12BC4796(十进制)或12BC(十六进制)5.浮点数浮点整型常量由一串十进制数字组成,可以带小数点、分数和指数部分。浮点数的表示方法:[±][n].[n][E|e][±][n]n,为一串十进制数,浮点数前可带加减号(+或-),且小数点必须指定。例如:99.e9——有效的数;99e9——非法。合法:.314,3.14,-.314e-19。6.汇编时间常数在程序中使用.set伪指令给一个符号赋值,该符号就成为一个汇编时间常数,等效于一个常数。为了使用表达式中的常数,赋给符号的必须是绝对值。例如:将常数值18赋给符号bei_hua。bei_hua.set18LD#bei_hua,A也可以用.set伪指令将符号常数赋给寄存器名。此时,该符号变成了寄存器的替代名。例如:AuxRl.setARlMVMMAuxRl,SP注意:常量不能进行符号扩展。如:0ACH等于十六进制的00AC或十进制172,不等于-84。7.字符常数字符常数是包括在单引号内的字符串。若单引号之间没有字符,则值为0。每个字符在内部表示为8位ASCII码。例如:‘a’内部表示为61h‘B’内部表示为42h8.字符串字符串是由双引号括起来的一串字符,最大长度是可以变化的,由要求字符串的伪指令来设置。字符在内部用8位ASCII码来表示。例如:“example”定义了一个长度为7的字符串:example8.字符串字符串可用于下列伪指令中:.copy——作为复制伪指令中的文件名.sect——作为命名段伪指令中的段名.setsect——作为该伪指令中的段地址.byte——作为数据初始化伪指令中的变量名.string——作为该伪指令的操作数注意:字符常数与字符串的差别。字符常数代表单个整数值。字符串只是一串字符。5.1.3汇编源程序中的符号汇编程序中的符号用于标号、常数和替代字符。1、由字母、数字以及下划线和美元符号(A~Z,a~z,0~9,_和$)等组成;2、符号名最多可长达200个字符;3、在符号中,第1位不能是数字,并且符号中不能含空格。1.标号作为标号的符号代表在程序中对应位置的符号地址。通常,标号是局部变量,在一个文件中局部使用的标号必须是唯一的。助记符操作码和汇编伪指令名(不带前缀“.”)为有效标号。标号分大小写。例如:ABC,Abc,abc是3个不同的符号。在调用汇编器时使用-c选项,可以不分大小写。标号还可以作为.global,.ref,.def或.bss等汇编伪指令的操作数。如:.globallabellable1NOPADDlabel,BBlabel12.符号常数符号也可被设置成常数值。为了提高程序的可读性,可以用有意义的名称来代表一些重要的常数值。伪指令.set和.struct/.tag/.endstruct可以用来将常数赋给符号名。注意:符号常数不能被重新定义。【例5.1.3】定义符号常数举例。N.set512;定义常数buffer.set4*Nnzg1.set1nzg2.set2nzg3.set3item.struct;item结构定义.intnzg1;常数偏移nzg1=1.intnzg2;常数偏移nzg2=2.intnzg3;常数偏移nzg2=3tang.endstructarray.tagitem;声明数组.bssarray,tang*N3.定义符号常数使用-d选项可以将常数值与一个符号等同起来。定义符号常数后,在汇编源文件中可用符号代替和它等同的值。定义格式:asm500-dname=[value]汇编命令汇编选项符号名称符号的值若value省略,则符号的值设置为l。检测类型及伪指令检测类型使用的伪指令存在不存在与值相等与值不等.if$isdefed("name").if$isdefed("name")=0.ifname=value.ifname!=value注意:内部函数$isdefed中的变量必须括在双引号内。引号表明变量按字面解释而不是作为替代字符。4.预先定义的符号常数汇编器有若干预先定义符号,包括:①美元符号$,代表段程序指针SPC的当前值;②映像寄存器符号,包括AR0~AR7;③映像寄存器由汇编器设置为符号。用于指定存储器模式。由-mk选项设置,默认值为0。5.替代符号可将字符串值(变量)赋给符号,使符号名与该变量等效,成为字符串的别名,这种用来代表变量的符号称为替代符号。当汇编器遇到替代符号时,将用字符串值替代符号。和符号常数不同,替代符号可以被重新定义。可在程序中的任何地方将变量赋给替代符号。例如:.asg"high",AR2;寄存器AR25.局部标号局部标号是一种特殊的标号,使用的范围和影响是临时性的。定义方法:①用$n来定义。n是0~9的十进制数;②用NAME?定义。NAME是任何一个合法的符号名。汇编器用紧随其后一个唯一数值的句点代替问号。注意:局部标号不能用伪指令来定义。局部标号可以被取消定义,并可以再次被定义或自动产生。取消局部变量的方法:①使用.newblock伪指令;②使用伪指令.sect,.text或.data改变段;③使用伪指令.include或.copy,进入include文件;④达到include文件的结尾,离开include文件。【例5.1.4】合法、非法局部标号$n举例。假设符号ADDRA,ADDRB,ADDRC已经在前面作了定义。Label1:LDADDRA,A;将ADDRA装入累加器ASUBADDRB,A;减去地址BBC$1,ALT;如果小于0,分支转移到$1LDADDRB,A;否则将ADDRB装入累加器AB$2;分支转移到$2$1LDADDRA,A;$1:将ADDRA装入累加器A$2ADDADDRC,A;$2:加上ADDRC.newblock;取消$1的定义,使它可被再次使用BC$1,ALT;若小于0,分支转移到$1STLA,ADDRC;存ACC的低16位到ADDRC$1NOP、、、、、、、、、、、错误、、、、、、、、、、、、、、、、、、、、没有.newblockBC$1,ALT;若小于0,分支转移到$1STLA,ADDRC;存ACC的低16位到ADDRC$1NOP;错误:$1被多次定义、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、【例5.1.5】name?形式的局部标号的使用方法。;局部标号’mylab’的第1个定义NOPmylab?NOPBmylab?.copy“a.inc”;包括文件中有‘mylab’第2次定义mylab?NOP;从包括文件中退出复位后,‘mylab’的第3个定义Bmylab?;在宏中‘mylab’的第4个定义,;为了避免冲突,宏使用不同的名称空间maymac.macromylab?NOPBmylab?.endmmymac;宏调用。引用‘mylab'的第3个定义Bmylab?;既不被宏调用复位,也不与定义在宏中的相同名冲突;改变段,允许‘mylab'的第5个定义.sect“Secto_One”NOPmylab?.word0NOPNOPBmylab?;.newblock伪指令,允许‘mylab'的第6个定义.newblockmylab?.word0NOPNOPBmylab?5.1.4汇编源程序中的表达式表达式可以是常数、符号,或者是由算术运算符分开的一系列常数和符号。有效表达式的值:-32768~32767影响表达式的主要因素:①圆括号()。圆括号内的表达式最先计算;不能用大括号{}或中括号[]代替圆括号()。②优先级。’C54x汇编器使用与C语言相似的优先级,优先级高的先计算;③从左到右运算。具有相同的优先级,按从左到右的顺序计算。序号符号运算操作求值顺序1+-~!取正、取负、按位求补、逻辑负从右至左2*/%乘法、除法、求模从左至右3+-加法、减法从左至右4^指数从左到右5<<>>左移、右移从左至右6<<=小于、小于等于从左至右7>>=大于、大于等于从左至右8!==不等于、等于从左至右9&按位与运算从左至右10∧按位异或运算从左至右11|按位或运算从左至右1.运算符’C54x汇编器使用与C语言相似的优先级。取正(+)、负(-)和乘(*)比二进制形式有较高的优先级。2.条件表达式汇编器支持关系运算符,可以用于任何表达式。=等于==等于!=不等于>=大于或等于<=小于或等于>大于<小于3.有效定义的表达式某些汇编器要求有效定义的表达式作为操作数。操作数是汇编时间常数或链接时可重定位的符号。有效定义的表达式是指表达式中的符号或汇编时间常数在表达式之前就已经被定义。有效定义的表达式的计算必须是绝对的。【例5.1.6】有效定义的表达式。.datalabel1.word0;将16位值0,1,2放入标号为label1的当前段连续字.word1.word2label2.word3;将3放入标号为label2的字中X.set50h;定义X的值goodsym1.setl00h+X;有效定义的表达式goodsym2.set$;引用已定义的所有局部标号goodsym3.setlabel1goodsym4.setlabel2-label1;有效定义的表达式【例5.1.7】无效定义的表达式。.globalY;定义Y为全局外部符号badsym1.setY;Y在当前文件中未定义badsym2.set50h+Y;无效的表达式badsym3.set50h+Z;无效的表达式,Z还未定义Z.set60h;定义Z,但应在表达式使用之前4.表达式上溢和下溢汇编时执行了算术操作以后,汇编器检查上溢和下溢的条件。当出现上溢或下溢时,汇编器会发出一个值被截断了的警告。汇编器不检查乘法的溢出状态。5.可重新定位符号和合法表达式对于绝对符号、可重新定位符号以及外部符号的有效操作,可参见下表。带有绝对符号和可重新定位符号的表达式如果A为…并且B为…A+B为…A-B为…绝对绝对绝对可重新定位可重新定位可重新定位外部外部外部绝对外部可重新定位绝对可重新定位外部绝对可重新定位外部绝对外部可重新定位可重新定位非法非法外部非法非法绝对非法非法可重新定位绝对非法外部非法非法表达式不能包含可重新定位符号和外部符号的乘或除;表达式中不能含有对其他的段为可重新定位的符号;用.global伪指令定义为全局的符号和寄存器也可以用在表达式中。这些符号和寄存器被声明为外部符号;可重新定位的寄存器也可以用在表达式中,这些寄存器的地址相对于定义它们的寄存器段是可重新定位的,除非将它们声明为外部符号。【例如】:在下面的程序中,使用了4个定义在相同段的符号。.globalextern_1;定义在外部的全局符号intern_1:.word‘’’D’;定义在现行模块中,可重新定位LAB1:.set2;LAB1=2,绝对符号intern_2:.word3;定义在现行模块中,可重新定位LD#LAB1+((5+4)*3),A;LAB1为绝对符号,A=29LD#LAB1+3+(4*7),A;LAB1为绝对符号,A=33所有合法表达式可以化简为两种形式:①可重新定位符号±绝对符号;②绝对符号。单操作数运算仅能应用于绝对符号,不能应用于可重新定位符号。表达式简化为仅含有可重新定位符号是非法的。【例5.1.8】判断下列指令中表达式的合法性。LDextern_1-10,B合法└──可重新定位LD10-extern_1,B非法└──不可将重新定位符号变负LD-(intern_1),B非法└──可重新定位符号不可变负LDextern_1/10,B非法└──可重新定位符号不可乘除LDintern_1+extern_1,B非法└──可重新定位+可重新定位=非法【例5.1.9】判断下列指令中表达式的合法性。LDintern_1-intern_2+extern_1,B可重新定位可重新定位可重新定义-可重新定义=绝对符号绝对符号可重新定位绝对符号+可重新定位→合法LDintern_1+intern_2+extern_1,B非法可重新定义+可重新定义=非法♂LDintern_1+extern_1-intern_2,B非法可重新定义+可重新定义=非法♂5.2堆栈的使用方法当程序调用中断服务程序或子程序时,需要将程序计数器PC的值和一些重要的寄存器值进行压栈保护,以便程序返回时能从间断处继续执行。’C54x提供一个用16位堆栈指针SP寻址的软件堆栈。当向堆栈中压入数据时,堆栈是从高地址向低地址方向填入,堆栈指针SP先减1,然后将数据压入堆栈。当从堆栈中弹出数据时。数据先从堆栈中弹出,然后堆栈指针SP加1。1.堆栈的设置若程序中要使用堆栈,必须先进行设置,如:size.set120在RAM中定义一个STACKtack.usect“STACK”,size的保留空间,共120个单元STM#stack+size,SP保留区的高地址赋给SP,作为堆栈的栈底在数据RAM空间开辟一个堆栈区。设置堆栈指针,#stack+size→SP。设置好堆栈后,就可以使用堆栈了,如:CALLpmad;(SP)-1→SP,(PC)+2→TOS,pmad→PCRET;(TOS)→PC,(SP)+1→SP2.堆栈区大小的确定堆栈区的大小可以按照以下步骤来确定:①先开辟一个较大的堆栈区,用已知数充填,如:LD#-9224,B;堆栈区要充填的数0DBF8h加载BSTM#length,AR1;设置循环次数MVMMSP,AR4;设置数据指针AR4,SP→AR4loop:STLB,*AR4-;循环,充填数据BANZloop,*AR1-堆栈区的大小可以按照以下步骤来确定:①先开辟一个较大的堆栈区,用已知数充填。②运行程序,执行所有堆栈操作。③检查堆栈中的数值。用过的堆栈区就是实际需要的堆栈空间。5.3控制程序’C54x具有丰富的程序控制指令,利用这些指令可以执行分支转移、子程序调用、子程序返回,条件执行以及循环等控制操作。5.3.1分支操作程序程序控制中的分支操作包括:分支转移程序子程序调用子程序返回条件操作程序通过传送控制到程序存储器的其他位置,分支转移会中断连续的指令流。分支转移指令可以改写PC值,使程序改变流向。其指令分为无条件分支转移和条件分支转移两类。两者都可以带延时操作和不带延时操作。分支转移指令分类指令说明无条件分支转移B[D]用该指令指定的地址加载PCBACC[D]用累加器的低16位指定的地址加载PC条件分支转移BC[D]若满足指令给定条件,用该指令指定的地址加载PCBANG[D]若当前选择辅助寄存器不等于0,用该指令指定的地址加载PC远程分支转移FB[D]用该指令指定的地址加载PC和XPCFBACC[D]用累加器的低23位指定的地址加载PC和XPC无条件分支转移:无条件执行分支转移;条件分支转移:要在满足用户一个或多个条件时才执行分支转移;远程分支转移:允许分支转移到扩展存储器。【例5.3.1】分支转移举例。STM#88H,AR0;将操作数#88H装入AR0LD#1000H,A;将操作数#1000H装入ACCzhong:SUBAR0,A;将A中的内容减去AR0中的;内容结果装入ABCzhong,AGT,AOV;若累加器A>0且溢出,;则转至zhong,否则往下执行与分支转移一样,通过传送控制到程序存储器的其他位置,子程序调用会中断连续的指令流。但是与分支转移不同的是,这种传送是临时的。当函数的子程序被调用时,紧跟在调用后的下一条指令的地址保存在堆栈中。这个地址用于返回到调用程序并继续执行调用前的程序。子程序调用操作分成两种形式:无条件调用和条件调用,两者都可以带延时操作和不带延时操作。2.子程序调用程序子程序调用指令分类指令说明无条件调用CALL[D]将返回的地址压入堆栈,并用该指令指定的地址加载PCCALA[D]将返回的地址压入堆栈,用累加器A或B指定的地址加载PC条件调用CC[D]如果满足指令给定条件,将返回的地址压入堆栈,并用该指令指定的地址加载PC远程调用FCALL[D]将XPC和PC压入堆栈,并用该指令指定的地址加载PC和XPCFCALA[D]将XPC和PC压入堆栈,用累加器的低23位指定的地址加载PC和XPC无条件调用是指无条件执行调用。条件调用和无条件调用操作相同,但是条件调用要在满足一个或多个条件时才执行调用。远程调用允许对扩展存储器的子程序或函数进行调用。【例5.3.2】子程序调用举例。STM#123H,AR0;将操作数#123H装入AR0LD#456H,AR1;将操作数#456H装入AR1CALLnew;调子程序newLDAR1,16,A;将AR1的内容左移16位后装入Anew:MPYAR0,AR1,A;AR0与AR1的内容相乘,结果放入A中RET;子程序返回3.子程序返回程序子程序返回程序可以使程序重新在被中断的连续指令处继续执行。返回指令通过将弹出堆栈的值(包含将要执行的下一条指令的地址),送到程序计数器PC来实现返回功能。’C54x可以执行无条件返回和条件返回,并且它们都可以带延时或不带延时操作。子程序返回指令分类指令说明无条件返回RET[D]将堆栈顶部的返回地址加载到PC。RETE[D]将堆栈顶部的返回地址加载到PC,并使能可屏蔽中断。RETF[D]将RTN寄存器中的返回地址加载到PC,并使能可屏蔽中断。条件返回RC[D]如果满足指令给定条件,将堆栈顶部的返回地址加载到PC。远程返回FCALL[D]将堆栈顶部的值弹出加载到XPC,将堆栈中下一个值弹出加载到PC。FCALA[D]将堆栈顶部的值弹出加载到XPC,将堆栈中下一个值弹出加载到PC,并使能可屏蔽中断。3.子程序程序无条件返回是无条件执行返回操作。条件返回可以给予被调用函数或中断服务程序(ISR)更多的返回方式,以便根据被处理的数据选择返回路径,通过使用条件返回指令来实现返回。远程返回允许从扩展存储器的子程序或函数返回。5.3.1分支操作’C54x的一些指令只有在满足一个或是多个条件后才被执行,如条件分支转移、条件调用和条件返回等指令。这些指令都用条件来限制分支转移、调用和返回操作。这些条件可用条件算符来表示。4.条件操作程序条件算符操作符号条件说明操作符号条件说明AEQA=0累加器A等于0AOVAOV=1累加器A溢出BEQB=0累加器B等于0BOVBOV=1累加器B溢出ANEQA¹0累加器A不等于0ANOVAOV=0累加器A不溢出BNEQB¹0累加器B不等于0BNOVBOV=0累加器B不溢出ALTA<0累加器A小于0CC=1ALU进位位置1BLTB<0累加器B小于0NCC=0ALU进位位置0ALEQA£0累加器A小于等于0TCTC=1测试/控制标志位置1BLEQB£0累加器B小于等于0NTCTC=0测试/控制标志位置0AGTA>0累加器A大于0BIOBIO低BIO信号电平为低BGTB>0累加器B大于0NBIOBIO高BIO信号电平为高AGEQA³0累加器A大于等于0UNC无无条件操作BGEQB³0累加器B大于等于0
在条件操作时也可以要求有多个条件,只有所有条件满足时才被认为是满足条件。这种多个条件的组合就构成了指令的多重条件。多重条件算符第1组第2组A类B类A类B类C类EQNEQLEQGEQLTGTOVNOVTCNTCCNCBIONBIO选用多重条件时应当注意以下几点:①第1组:分为两类,最多可选择两个条件,组内两类条件可以与/或构成多重条件,但不能用组内同类条件构成与/或多重条件。当选择两个条件时,累加器必须是同一个。例如,可以同时选择AGT和AOV,但不能同时选择AGT和BOV。②第2组:分为三类,最多可选三个条件,可以在每类中各选一个条件进行与/或构成多重条件,但不能在同类选两个以上条件。例如,可以同时测试TC、C和BIO,但不能同时测试NTC、C和NC。③组与组之间可用或构成多重条件。【例5.3.3】条件操作程序。BCsub,BLEQ;条件分支转移若累加器B≤0,则转至sub,否则,往下执行CCstart,AGEQ,AOV;条件调用若累加器A≥0且溢出,则调用start,否则往下执行RCNTC;条件返回若TC=0,则返回,否则往下执行【注意】:若需要多个条件相与时,用单条指令表示。如:BCnew,AGT,AOV转移条件:AGT和AOV的与逻辑若需要两个条件相或时,需用两条指令分别表示。如:若累加器A大于0或溢出,则转移至sub转移条件:AGT和AOV的或逻辑BCsub,AGTBCsub,AOV5.3.1分支操作程序5.比较转移程序利用比较指令CMPR可实现比较转移操作。比较操作指令:CMPR测试条件,辅助寄存器ARx指令功能:辅助寄存器ARx与AR0进行比较,若比较结果使所给定的测试条件成立,则TC位置1。实现方法:①通过CMPR的比较结果得TC值;②根据TC值,由条件转移指令实现分支转移。例如:比较操作后条件分支转移STM#5,AR1;AR1=5STM#10,AR0;AR0=10loop:……*AR1+;AR1=AR1+1……CMPRLT,AR1;若AR1-AR0<0,则TC=1,否则为0BCloop,TC;若AR1-AR0<0,则循环若AR1=AR0,则顺序执行5.3.2循环操作程序在程序设计时,经常需要重复执行某一段程序。利用BANZ(当辅助寄存器不为0时转移)指令可实现循环计数和操作。循环操作指令:BANZ转移地址,辅助寄存器指令功能:当辅助寄存器不为0时,则转至转移地址,否则顺序执行。【例5.3.4】用AR2作为循环计数器,由BANZ实现程序的循环控制。.bssx,10;给x保留10个空间.bssy,1;给y保留1个空间STM#x,AR1;设置数据段的首地址STM#9,AR2;设置循环计数值LD#0,A;累加器清0loop:ADD*AR1+,A;累加运算,并修改地址BANZloop,*AR2-;若计数值不为0,则循环,并计数值减1若计数值为0,则结束循环STLA,@y;累加和存入y中注意:BANZloop,*AR2-;先判断,再修正AR2=AR2-15.4算术运算程序基本算术运算包括:加减法和乘法运算除法运算长字和并行运算5.4.1加、减法和乘法在数字信号处理中,加法和乘法运算是最常见的算术运算。【例】计算y=a×x+b程序:LD@a,T;取a值,T=aMPY@x,B;完成ax乘积,B=axADD@b,B;完成ax+b运算,B=ax+bSTLB,@y;计算结果存入y中【例】计算y=xl×al+x2×a2程序:LD@x1,T;T=x1MPY@a1,B;B=x1a1LD@x2,T;T=x2MAC@a2,B;乘法累加,B=x1a1+x2a2STLB,@y;计算结果的低字BL存入y中STHB,@y+1;计算结果的高字BH存入y+1中【例5.4.3】计算程序:*********************************************example.asm*********************************************.title“example.asm”.mmregsstack.usect“STACK”,10h;为堆栈指定空间.bssa,4;为变量分配9个字的空间.bssx,4.bssy,1.defstart.datatable:.word1,2,3,4;变量初始化.word8,6,4,2.textstart:STM#0,SWWSR;插入0个等待状态STM#STACK+10h,SP;设置堆栈指针STM#a,AR1;AR1指向aRPT#7;移动8个数据MVPDtable,*AR1+;从程序存储器到数据存储器CALLSUM;调用SUM子程序end:BendSUM:STM#a,AR3;子程序执行STM#x,AR4RPTZA,#3MAC*AR3+,*AR4+,ASTLA,@yRET.end【例】求4项乘积aixi(i=1,2,3,4)中的最大值,并存放累加器A中。程序:STM#a,AR1;ai首地址a给AR1STM#x,AR2;xi首地址x给AR2STM#2,AR3;设置计数器AR3=2LD*AR1+,T;取系数T=ai,并修改AR1MPY*AR2+,A;乘法运算A=aixi,并修改AR2loop1:LD*AR1+,T;取系数T=ai,并修改AR1MPY*AR2+,B;乘法运算B=aixi,并修改AR2MAXA;求A和B中的最大值BANZloop1,*AR3-;若AR3≠0,则循环,并修改AR3若AR3=0,则不循环5.4.2除法运算在’C54x中没有除法器硬件,也没有专门的除法指令。但是,利用条件减法指令(SUBC)和重复指令(RPT)可实现两个无符号数的除法运算。条件减法指令:SUBCSmem,src功能:(src)-(Smem)<<15→ALU输出端若ALU输出0,则(ALU输出)<<1+1→src否则(src)<<1→src重复指令:RPT#K功能:RC=#K,重复执行下条指令K+1次。1.|被除数|<|除数|例:编写0.4÷(-0.8)的程序.bssnum,1.bssden,1.bssquot,1.datatable.word4*32768/10;0.4.word-8*32768/10;-0.8.textstart:STM#num,AR1RPT#1LD@den,16,A;分母送AHMPYA@num;商符号送B(num)×AH→B,即分子×分母→B,取符号。ABSA;取分母绝对值STHA,@denLD@num,16,A;分子送AHABSA;取分子绝对值RPT#14;15次减法循环SUBC@den,A;完成除法XC1,BLT;若B<0,则变号NEGASTLA,@quot;保存商运行结果:被除数除数商(十六进制)商(十进制)4*32768/100(0.4)-8*32768/100(-0.8)0xC000-0.5-12810240xF000-0.1252.|被除数|>|除数|例:编写16384÷512的程序.bssnum,1.bssden,1.bssquot,1.datatable.word16384;16384.word512;512.textstart:STM#num,AR1RPT#1MVPDtable,*AR1+;传送2个数据至分子、分母单元LD@den,16,A;将分母移到累加器A(31~16)MPYA@num;(num)*A(32~16)→B,获取商的符号ABSA;分母取绝对值STHA,@den;分母绝对值存回原处LD@num,A;分子→A(32~16)ABSA;分子取绝对值RPT#15;16次减法重复操作,完成除法SUBC@den,AXC1,BLT;如果B<0(商是负数),则需要变号NEGASTLA,@quot;保存商运行结果:被除数除数商(十六进制)商(十进制)163845120xC0203266*32768/100(0.66)-33*32768/100(-0.33)0xFFFE-2注意:SUBC指令仅对无符号数进行操作,因此先对被除数和除数取绝对值,然后利用乘法操作获取商的符号,最后通过条件操作指令给商加上适当的符号。5.4.3长字运算和并行1.长字运算’C54x可以利用32位长操作数进行长字运算。长字指令:DLDLmem,dst;dst=Lmem单周期DSTsrc,Lmem;Lmem=src双周期DADDLmem,src[,dst];dst=src+Lmem单周期DSUBLmem,src[,dst];dst=src-Lmem单周期DRSUBLmem,src[,dst];dst=Lmem-src单周期(1)偶地址排列指令中给出的地址为偶地址,则存储器低地址存放高16位操作数。如:DLD*AR3+,A执行前:A0000000000AR30100数据存储器┌①─(AR30101)─0100h6CAC高字执行后:A006CACBD90②←0101HBD90低字AR30102【例5.4.5】偶地址排列法举例。.bssa,2.bssy,2.datatable:.word06CACH,0BD90H.text…STM#a,AR1RPT#1MVPDtable,*AR1+STM#a,AR3DLD*AR3+,A执行前:A=0000000000hAR3=0100h(0100h)=6CACh(高字)(0101h)=BD90h(低字)执行后:A=006CACBD90hAR3=0102h(0100h)=6CACh(0101h)=BD90h1.长字运算(2)奇地址排列指令中给出的地址为奇地址,则存储器低地址存放低16位操作数。如:DLD*AR3+,A执行前:A0000000000AR30101数据存储器┌②─(AR30103)─0100h6CAC低字执行后:A00BD906CAC①←0101HBD90高字AR30103【例5.4.6】奇地址排列法举例。.bssa,2.bssy,2.datatable:.word06CACH,0BD90H.text…STM#a,AR1RPT#1MVPDtable,*AR1-STM#a,AR3DLD*AR3+,A执行前:A=0000000000hAR3=0101h(0100h)=6CACh(低字)(0101h)=BD90h(高字)执行后:A=00BD906CAChAR3=0103h(0100h)=6CACh(0101h)=BD90h【例5.4.7】计算Z32=X32+Y32。标准运算.bssxhi,1.bssxlo,1.bssyhi,1.bssylo,1.bsszhi,1.bsszlo,1…LD@xhi,16,AADDS@xlo,AADD@yhi,16,AADDS@ylo,ASTHA,@zhiSTLA,@zlo6字,6T长字运算.bssxhi,2,1,1.bssyhi,2,1,1.bsszhi,2,1,1…DLD@xhi,ADADD@yhi,ADSTA,@zhi3字,3T5.4.3长字运算和并行2.并行运算并行运算就是同时利用D总线和E总线,通过并行指令来实现数据的加载和算术运算。D总线用来执行加载或算术运算。E总线用来存放先前的结果。并行指令:并行加载和乘法指令并行加载和存储指令并行存储和乘法指令并行存储和加/减指令并行加载和乘法指令:LD||MAC[R]LD||MAS[R]例如:LDXmem,dst1||MAC[R]Ymem,[,dst2]功能:dst1=Xmem<<16;dst2=dst2+T*Ymem。并行加载和存储指令:ST||LD例如:STsrc,Ymem||LDXmem,dst功能:Ymem=src>>(16-ASM);dst=Xmem<<16。并行存储和乘法指令:ST||MPYST||MAC[R]ST||MAS[R]例如:STsrc,Ymem||MAC[R]Xmem,dst功能:Ymem=src>>(16-ASM);dst=dst+T*Xmem。并行存储和加/减指令:ST||ADDST||SUB例如:STsrc,Ymem||ADDXmem,dst功能:Ymem=src>>(16-ASM);dst=dst+Xmem。【注意】并行指令均为单字单周期指令;并行指令先存储,后加载或算术运算;并行指令的操作均在累加器的高位中进行,并且大多数指令受ASM位的影响。【例5.4.8】编写计算z=x+y和f=e+d的程序·bssx,3·bssd,3STM#x,AR5STM#d,AR2LD#0,ASMLD*AR5+,16,AADD*AR5+,16,ASTA,*AR5||LD*AR2+,BADD*AR2+,16,BSTHB,AR25.4.3长字运算和并行3、64位加法和减法运算可利用长字指令可完成64位数的加减运算。【例5.4.9】编写完成Z64=W64+X64-Y64的程序。运算过程:S64=s3s2s1s0s1s0=w1w0+x1x0s3s2=w3w2+x3x2+CZ64=z3z2z1z0z1z0=s1s0-y1y0z3z2=s3s2-y3y2-0程序:DLD@w1,A;A=w1w0DADD@x1,A;A=s1s0,产生CDLD@w3,B;B=w3w2ADDC@x2,B;B=w3w2+x2+CADD@x3,16,B;B=s3s2=w3w2+x3x2+CDSUB@y1,A;A=s1s0-y1y0,产生0DSTA,@z1;z1z0=s1s0-y1y0SUBB@y2,B;B=s3s2-y2-0SUB@y3,16,B;B=z3z2DSTB,@z3;z3z2=s3s2-y3y2-04、32位乘法运算【例】编写完成W64=X32×Y32的程序。运算过程:w0=x0y0Lw1=x0y0H+x1y0L+y1x0Lw2=x1y0H+y1x0H+y1x1Lw3=y1x1H乘法运算:U×US×US×S乘法指令:MPYUSmem,dst;dst=U(T)×U(Smem)MACSUXmem,Ymem,src;src=U(Xmem)×S(Ymem)+srcMACXmem,Ymem,src;src=S(Xmem)×S(Ymem)+src程序:STM#x0,AR2;AR2←x0STM#y0,AR3;AR3←y0LD*AR2,T;T=x0MPYU*AR3+,A;A=u(x0)×u(y0)STLA,@w0;(w0)←ALDA,-16,A;A=x0y0HMACSU*AR2+,*AR3-,A;A=y1x0+x0y0HMACSU*AR3+,*AR2,A;A=x1y0+y1x0+x0y0HSTLA,@w1;(w1)←ALDA,-16,A;A=y1x0H+x1y0HMAC*AR2,*AR3,A;A=y1x1+y1x0H+x1y0HSTLA,@w2;(w2)←ASTHA,@w3;(w3)←A5.5重复操作程序’C54x的重复操作是使CPU重复执行一条指令或一段指令。可以分为单指令重复和块程序重复。实现重复操作的指令:RPT——重复下条指令;RPTZ——累加器清0,并重复下条指令;RPTB——块重复指令。使用RPT、RPTZ能重复下一条指令;而RPTB用于重复代码块若干次。利用重复指令可实现比BANZ指令更快的循环程序。利用RPT和RPTZ可重复执行紧随其后的一条指令。重复次数由该指令的操作数决定,并且等于操作数加1。若要重复执行N+1次,则重复指令中应规定重复次数为N。该数值保存在16位重复计数器RC中,可通过RPT或RPTZ指令加载。一条指令的最大重复次数为65536。由于要重复的指令只需要取指一次,对于多周期指令,采用重复操作后,可使多周期指令变成单周期指令,提高运行速度。5.5.1单指令重复【例5.5.1】对数组进行初始化,使x[8]={0,0,0,0,0,0,0,0}。.bssx,8STM#x,AR1LD#0,ARPT#7STLA,*AR1+↓↓↓↓↓↓↓↓↓↓↓↓↓↓.bssx,8STM#x,AR1RPTZA,#7STLA,*AR1+【注意】:①对x[8]中的8个元素置0,重复次数为7,即执行1次STLA,AR1+指令后,再重复执行7次;②RPTZ指令设定重复次数后,再对累加器清零。在执行重复操作期间,除了RS外所有中断被禁止,直到重复循环完成。’C54x能响应HOLD信号,若HM=0,CPU继续执行重复操作,若HM=1,则暂停重复操作。5.5.2块程序重复对于整个程序块需要重复操作时,可采用程序块重复操作。用于块程序重复操作指令为RPTB和RPTBD。程序块的长度由块程序重复指令RPTB的操作数来确定,而重复次数由块重复计数器BRC来决定。通常RPTB的操作数为程序块的结束地址,而重复次数可用STM指令对BRC进行设定。块重复操作的特点:①程序块的起始地址RSA是RPTB指令的下一行;②块结束地址REA由RPTB指令的操作数规定;③对程序块进行重复操作时,不论程序块多长,重复次数多大,所用的机器周期为0;④与单指令重复操作不同,块重复操作可以响应中断。块程序重复指令的特点是对任意长程序段的循环开销为0。循环由ST1状态寄存器的块重复标志位(BRAF)和紧跟在ST1状态寄存器后面的存储器映像寄存器控制。循环过程:①将块重复标志位BRAF置1,激活块程序重复循环;②将一个取值在0~65535范围里的循环次数N加载到BRC;③块重复指令把块重复的起始地址放在块重复开始地址寄存器RSA中;④块重复指令把块重复的末地址放在块重复结束地址寄存器REA中。5.5.2块程序重复【例5.5.2】对数组x[8]中的每一元素加1。.bssx,8;设置数组空间begin:LD#1,16,B;立即数1送入BHSTM#7,BRC;设置重复次数,BRC=7,循环8次STM#x,AR4;数组首地址x送入AR4RPTBnext-1;设置循环结束地址ADD*AR4,16,B,A;数组数据左移16位与BH相加STHA,*AR4+;存入数组结果,并修改地址next:LD#0,B;B清0…【注意】①块结束地址REA通常取程序块最后一条指令的下一条指令地址-1;②重复次数为7次③RPTB指令可以响应中断。5.5.3循环嵌套循环嵌套是程序编制中常用的技巧,可以用来简化较为复杂的程序。块程序重复指令RPTB所用的寄存器有:BRC——重复计数器;RSA——起始地址寄存器;REA——结束地址寄存器。RPT重复操作可以和块重复操作RPTB以及循环操作BANZ进行嵌套,实现多重嵌套。【例5.5.2】三重循环嵌套程序。三重循环嵌套结构:内层——RPT——执行N次中层——RPTB——执行M次外层——BANZ——执行L次循环嵌套的开销循环操作指令重复次数机器周期内层单程序重复操作RPTN1中层块程序重复操作RPTBM4+25.6数据块传送程序可以用于数据传送的指令有10条,分别可以实现数据存储器之间、数据存储器和MMR之间、程序存储器和数据存储器之间、程序存储器和数据存储器之间的数据块传送等。这些指令传送速度比加载和存储指令快,传送数据不需要通过累加器,可以寻址程序存储器,与RPT指令相结合可以实现数据块传送。1.数据传送指令用于数据传送指令可分为四类:(1)数据存储器之间的数据传送MVDKSmem,dmad2字2周期MVKDdmad,Smem2字2周期MVDDXmem,Ymem1字1周期(2)数据存储器与MMR之间的数据传送MVDMdmad,MMR2字2周期MVMDMMR,dmad2字2周期MVMMMMRx,MMRy1字2周期(3)程序存储器和数据存储器之间的数据传送MVPDpmad,Smem2字3周期MVDPSmem,pmad2字4周期READASmem1字5周期WRITASmem1字5周期(4)从PA口读/写数据PORTRPA,Smem2字2周期PORTWSmem,PA2字2周期数据传送指令的特点①
传送速度比加载和存储指令要快;②数据传送不通过累加器;③
可寻址程序存储器;④与RPT结合,可实现数据块传送。2.程序存储器至数据存储器的数据传送重复执行MVPD指令,可以实现程序存储器至数据存储器的数据传送,在系统初始化过程中十分有用。【例5.6.1】数组x[8]={0,1,2,3,4,5,6,7}初始化。.bssx,8.dataTBL:.word0,1,2,3,4,5,6,7.textSTART:STM#x,AR5RPT#7MVPDTBL,*AR5+……3.数据存储器之间的数据传送在数字信号处理时,经常需要将数据存储器中的一批数据传送到数据存储器的另一个地址空间。【例5.6.2】进行N点FFT运算时,为节约存储空间要用到原位计算,将数组X[16]赋到数组Y[16],计算一个蝶形后,所得输出数据可以立即存入原输入数据所占用的存储单元。.bssx,16.bssy,16…STM#x,AR2STM#y,AR3RPT#15MVDDAR2+,*AR3+4.数据存储器和MMR之间的数据传送【例5.6.4】双操作数方式实现IIR高通滤波器:table:.word0;x(n-2).word0;x(n-1).word653*32768/10000;x(n-0).word-1306*32768/10000;B2.word653*32768/10000;B0.word-3490*32768/10000;A2.word-600*32768/10000;A1/2.textstart:SSBXFRCTSTM#x2,AR1RPT#1MVPD#table,*AR1+【例5.6.4】双操作数方式实现IIR高通滤波器:STM#COEF,AR1RPT#4MVPD#table+2,*AR1+STM#x2,AR3STM#COEF+4,AR4;AR4指向A1MVMMAR4,AR1;保存地置值在AR1中STM#3,BK;设置循环缓冲区长度STM#-1,AR0;设置变址寻址步长IIR1:PORTRPA1,*AR3;从PA1口输入数据x(n)LD*AR3+0%,16,A;计算反馈通道。A=x(n)MAC*AR3,*AR4,A;A=x(n)+A1*x1MAC*AR3+0%,*AR4-,A;A=x(n)+A1*x1+A1*x1【例5.6.4】双操作数方式实现IIR高通滤波器:MAC*AR3+0%,*AR4-,A;A=x(n)+2*A1*x1+A2*x2=x0STHA,*AR3;保存x0MPY*AR3+0%,*AR4-,A;计算前向通道。A=B0*x0MAC*AR3+0%,*AR4-,A;A=B0*x0+B1*x1MAC*AR3,*AR4-,A;A=B0*x0+B1*x1+B2*x2=y(n)STHA,*AR3;保存y(n)MVMMAR1,AR4;AR4重新指向A1BDIIR1;循环PORTW*AR3,PA0;向PA0口输出数据.end5.7小数运算程序在定点DSP芯片中,采用定点数进行数值运算时,若操作数采用整型数,则DSP芯片给定的字长(一般16位)决定了整型数的最大范围。通常,定点DSP采用小数乘法。其原因:①乘法器为16位,对于大于16位的数据难以实现乘法递推,且乘积占用存储资源大;②小数乘法时,既可以存储32位乘积,也可以存储高16位乘积,可用较少的资源保存结果;③小数乘法便于乘法递推。1.数的定标采用小数运算时,设定小数点在16位中的位置称为定标。小数点在16位数中的位置不同,可以表示不同大小和不同精度的小数。数的定标通常有Q表示法,如Q0,Q1,…,Q15。Q越大,可以表示的数的范围越小,但精度越高。在具体的定点程序中,必须根据具体情况适当选择合适的定标。2.小数的表示方法’C54x采用基于2的补码小数表示形式。每个16位数用1个符号位(最高位)、i个整数位、15-i个小数位来表示。采用2的补码小数(Q15格式),其位权值为:MSB……LSB-1.2-12-22-3…2-15例如:00000010.10100000——21+2-1+2-3=2.6252的补码小数表示方法:将十进制小数乘以32768,并将整数乘积转换成16进制数。正数:乘以32768,整数转换成16进制数;负数:其绝对值乘以32768,整数取反加1。如:1——7FFFH1×32768=7FFFH0.5——4000H0.5×32768=4000H0.25——2000H0.25×32768=2000H0——0000H0×32768=0000H-0.25——E000H(0.25×32768)补=E000H-0.5——C000H(0.5×32768)补=C000H-1——8000H(1×32768)补=8000H【注意】:汇编时,不能直接写成十进制小数。如:0.907——.word32768*907/10003.小数乘法与冗余符号位小数乘法实例:0.625´(-0.125)=-0.078125乘积:-0.078125=11010007位二进制扩展8位后,乘积:11101000=-0.1865出错原因:两带符号数相乘,其结果带有2个符号位。Sxxx(Q3格式)×Syyy(Q3格式)SSzzzzzz(Q6格式)解决办法:运算结果左移一位,消去多余符号位。可通过对FRCT位置1,乘法器自动
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 齐鲁工业大学《Java面向对象的程序设计》2022-2023学年期末试卷
- 光伏发电运维合同
- 保育老师培训计划
- 保安服务管理制度范文
- 化学品安全生产技术管理考核试卷
- 2024年陕西省安全员A证考试试题题库
- 光学显微镜的放大倍率与视场角度研究考核试卷
- 日用化学产品的健康风险考核试卷
- 建筑物拆除电缆与设备拆除考核试卷
- 托儿所服务的教师素养与专业发展考核试卷
- 货物质量保证措施方案
- 黑龙江省龙东地区2024-2025学年高二上学期阶段测试(二)(期中) 英语 含答案
- 4S店展厅改造装修合同
- 3-4单元测试-2024-2025学年统编版语文六年级上册
- 北师版数学八年级上册 5.8三元一次方程组课件
- 2024混合动力汽车赛道专题报告-2024-10-市场解读
- 企业单位消防安全规范化管理指导手册
- 废旧物资回收投标方案(技术方案)
- 宣传视频拍摄服务投标方案(技术方案)
- 森林防火课件下载
- 3《欢欢喜喜庆国庆》(教学设计)2024-2025学年统编版道德与法治二年级上册
评论
0/150
提交评论