




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第第6章章 TMS320C64x DSP的的C/C+程序程序设计设计n6.1 C/C+程序设计基础程序设计基础n6.2 程序设计示例程序设计示例n6.3 用用C语言和汇编语言混合编程语言和汇编语言混合编程6.1 C/C+程序设计基础程序设计基础DSP生产厂商及第三方为生产厂商及第三方为DSP软件开发提供了软件开发提供了C编译器,编译器,使得利用高级语言实现使得利用高级语言实现DSP程序的开发成为可能。程序的开发成为可能。在在TI公司的公司的DSP软件开发平台软件开发平台CCS中,又提供了优化的中,又提供了优化的C编译器,可以对编译器,可以对C语言程序进行优化编译,提高程语言程序进行优化编译,提
2、高程序效率,目前在某些应用中,序效率,目前在某些应用中,C语言优化编译的结果语言优化编译的结果可以达到手工编写的汇编语言效率的可以达到手工编写的汇编语言效率的90%以上。以上。DSP生产厂商和相关公司也在不断对生产厂商和相关公司也在不断对C优化编译器进行优化编译器进行改进设计,改进设计,C语言程序优化编译的效果将会进一步改语言程序优化编译的效果将会进一步改善。善。返回首页6.1.1 面向面向DSP的程序设计原则的程序设计原则n面向面向DSP的的C/C+程序设计和通用计算机上的程序设计和通用计算机上的C/C+程序程序设计从本质和工作原理上来说是一致的,但受硬件资源和设计从本质和工作原理上来说是一
3、致的,但受硬件资源和处理对象的不同,存在一些区别:处理对象的不同,存在一些区别:DSP的数据存储区有限,的数据存储区有限,所以只能实时处理小批量数据;所以只能实时处理小批量数据;DSP代码需要绝对定位,代码需要绝对定位,计算机的计算机的C代码由操作系统定位。代码由操作系统定位。nDSP的的C/C+程序设计原则:程序设计原则: 灵活使用嵌入式灵活使用嵌入式C语言中的位操作指令;语言中的位操作指令; 编译系统不允许有太多的程序嵌套;编译系统不允许有太多的程序嵌套; 需要考虑对需要考虑对DSP硬件的时序要求;硬件的时序要求; 区别不同库函数的使用;区别不同库函数的使用; 不同存储类型变量的使用;不同
4、存储类型变量的使用; 尽可能模块化设计。尽可能模块化设计。类型类型大小大小数据格式数据格式最小值最小值最大值最大值Signed char16位位ASCII3276832767char, unsigned char16位位ASCII065535short, signed short16位位二进制补码二进制补码3276832767unsigned short16位位二进制二进制065535int, signed int16位位二进制补码二进制补码3276832767unsigned int16位位二进制二进制065535long, signed long32位位二进制补码二进制补码-2147483
5、6482147483647unsigned long32位位二进制二进制04294967295enum16位位二进制补码二进制补码3276832767float32位位IEEE 32位位1.175494e-383.40282346e38double32位位IEEE 32位位1.175494e-383.40282346e38long double32位位IEEE 32位位1.175494e-383.40282346e38pointers16位位二进制二进制00 x0FFFF表表6.1 CCS中中C语言数据类型语言数据类型6.1.2 C/C+语言数据类型语言数据类型6.1.5 C/C+的的DSP访
6、问规则访问规则1.DSP片内寄存器的访问片内寄存器的访问n CCS工程中的头文件与其它基于工程中的头文件与其它基于C语言的开发环境中的语言的开发环境中的头文件基本相同,主要是用来定义工程中的常量和数据结头文件基本相同,主要是用来定义工程中的常量和数据结构。为了提高开发效率,开发人员往往会将构。为了提高开发效率,开发人员往往会将DSP片内的控片内的控制寄存器定义写成一个头文件(如制寄存器定义写成一个头文件(如reg.h),这样在各个基),这样在各个基于相同型号于相同型号DSP的开发中,可以共享这个定义控制寄存器的开发中,可以共享这个定义控制寄存器的头文件。的头文件。n在在C语言中对语言中对DSP
7、片内寄存器一般采用指针方式来访问,片内寄存器一般采用指针方式来访问,所以常常采用的方法是将所以常常采用的方法是将DSP寄存器地址的列表定义在头寄存器地址的列表定义在头文件,中如下所示:文件,中如下所示:#define IMR (volatile unsigned int *)0 x0000#define IFR (volatile unsigned int *)0 x0001#define ST0 (volatile unsigned int *)0 x0006#define ST1 (volatile unsigned int *)0 x0007#define AL (volatile un
8、signed int *)0 x0008#define AH (volatile unsigned int *)0 x0009#define AG (volatile unsigned int *)0 x000A#define BL (volatile unsigned int *)0 x000B#define BH (volatile unsigned int *)0 x000C#define BG (volatile unsigned int *)0 x000D#define T (volatile unsigned int *)0 x000E#define TRN (volatile u
9、nsigned int *)0 x000F#define AR0 (volatile unsigned int *)0 x0010#define AR1 (volatile unsigned int *)0 x0011#define AR2 (volatile unsigned int *)0 x0012#define SP (volatile unsigned int *)0 x0018#define BK (volatile unsigned int *)0 x0019#define BRC (volatile unsigned int *)0 x0001A#define RSA (vol
10、atile unsigned int *)0 x001B#define REA (volatile unsigned int *)0 x001C#define PMST (volatile unsigned int *)0 x001D#define XPC (volatile unsigned int *)0 x001E在用户程序中,若要读出或者写入一个特定的寄存器,就要在用户程序中,若要读出或者写入一个特定的寄存器,就要对相应的指针进行操作。对相应的指针进行操作。下例通过指针操作对下例通过指针操作对ST0和和AR1进行初始化进行初始化Int userfunc()*ST0=0 x1278;*A
11、R1=0 x6013;2.DSP内部和外部存储器的访问规则内部和外部存储器的访问规则 DSP对存储器的访问也采用指针方式。对存储器的访问也采用指针方式。例:例: 对内部存储器单元对内部存储器单元0 x4000和外部存储器单元和外部存储器单元0 x80FF进行操作。进行操作。 int *data1= 0 x4000; int *data2= 0 x80FF; int userfunc( )*data1=7000;*data2= 0;3.DSP I/O端口的访问规则端口的访问规则n在在C语言中读写语言中读写DSP的的I/O端口空间,用关键字端口空间,用关键字ioport实现。实现。n用关键字用关键
12、字ioport定义定义I/O端口的格式如下:端口的格式如下: ioport type porthex_num其中其中ioport是关键字,指出这是一个是关键字,指出这是一个I/O端口变量。端口变量。type只能是只能是char、short、int或或unsigned这几种数据类型。这几种数据类型。porthex_num是端口号,是端口号,hex_num是一个十六进制数。是一个十六进制数。n所有端口变量都必须在文件级定义,不能在函数中定义。所有端口变量都必须在文件级定义,不能在函数中定义。下面的代码定义下面的代码定义I/O端口为端口为unsigned port 10h,将数据将数据a写入写入po
13、rt 10h,然后从然后从port 10h读入数据存到读入数据存到b中:中:Ioport unsigned port10 ; /*端口说明端口说明*/int func()port10=a ; /*数据数据a写入写入port 10h */b=port10 ; /*从从port 10h读出数据存到读出数据存到b */n端口变量不仅可在分配端口中使用,也可像其他变端口变量不仅可在分配端口中使用,也可像其他变量一样使用量一样使用a=port10 +b /*从从port 10h读入数据并加上数读入数据并加上数据据b,再存到,再存到a中中 */port10=a /*从从port 10h读出数据并加上数据读
14、出数据并加上数据a,将结果从将结果从port 10h输出输出 */n在函数调用时,在函数调用时,I/O端口变量的数值可以传递,但端口变量的数值可以传递,但I/O端口变量本身不能当作函数参数。端口变量本身不能当作函数参数。例:例:call(port10); /*从从port 10h读出数据读出数据,将该数据作为参将该数据作为参数并调用相应子函数数并调用相应子函数*/call(&port10); /*无效的参数传递无效的参数传递*/6.3 C语言和汇编语言混合编程语言和汇编语言混合编程n6.3.1 独立的独立的C模块和汇编模块接口模块和汇编模块接口n6.3.2 从从C程序中访问汇编程序变量
15、程序中访问汇编程序变量n6.3.3 在在C程序中直接嵌入汇编语句程序中直接嵌入汇编语句n 返回首页n用用C语言和汇编语言混合编程,能充分利用语言和汇编语言混合编程,能充分利用DSP芯片的资源,更好地发挥芯片的资源,更好地发挥C语言和汇编语言进行语言和汇编语言进行软件开发的各自的优点,可以将两者有机结合起软件开发的各自的优点,可以将两者有机结合起来,兼顾两者的优点,避免其弊端。因此,在很来,兼顾两者的优点,避免其弊端。因此,在很多情况下,采用混合编程方法能更好地达到设计多情况下,采用混合编程方法能更好地达到设计要求,完成设计功能。要求,完成设计功能。C语言和汇编语言的混合编程有以下几种方法:语言
16、和汇编语言的混合编程有以下几种方法:(1)独立编写汇编程序和)独立编写汇编程序和C程序,分开编译或汇程序,分开编译或汇编形成各自的目标代码模块,用链接器将编形成各自的目标代码模块,用链接器将C模块模块和汇编模块链接起来,这是一种灵活性较大的方和汇编模块链接起来,这是一种灵活性较大的方法。法。 (2)在)在C程序中直接内嵌汇编语句程序中直接内嵌汇编语句(3)将)将C程序编译生成相应的汇编程序,手工修程序编译生成相应的汇编程序,手工修改和优化改和优化C编译器生成的汇编代码。编译器生成的汇编代码。n独立编写汇编程序和独立编写汇编程序和C程序,分开编译或汇编形成各自的目程序,分开编译或汇编形成各自的目
17、标代码模块,用链接器将标代码模块,用链接器将C模块和汇编模块链接起来,这是模块和汇编模块链接起来,这是一种灵活性较大的方法。一种灵活性较大的方法。采用这种方法,采用这种方法,C程序可以调用汇编程序,并且可以访问汇程序可以调用汇编程序,并且可以访问汇编程序中定义的变量。同样,汇编程序也可以调用编程序中定义的变量。同样,汇编程序也可以调用C程序或程序或访问访问C程序中定义的变量。程序中定义的变量。 n 但用户必须自己维护各汇编模块的入口和出口代码,自己但用户必须自己维护各汇编模块的入口和出口代码,自己计算传递的参数在堆栈中的偏移量,工作量稍大,但能做到计算传递的参数在堆栈中的偏移量,工作量稍大,但
18、能做到对程序的绝对控制。对程序的绝对控制。n在编写在编写C程序和汇编程序时,必须遵循有关的寄存器规则和程序和汇编程序时,必须遵循有关的寄存器规则和函数调用规则。函数调用规则。 6.3.1 独立的独立的C模块和汇编模块接口模块和汇编模块接口寄存器规则明确了编译器如何使用寄存器以及在函数调用过程寄存器规则明确了编译器如何使用寄存器以及在函数调用过程中如何保护寄存器。如果汇编程序不符合寄存器使用规则,则中如何保护寄存器。如果汇编程序不符合寄存器使用规则,则C运行环境将会被破坏。运行环境将会被破坏。(1)辅助寄存器辅助寄存器:AR1、 AR6、 AR7由被调用函数保护;由被调用函数保护; AR0、 A
19、R2、 AR3、 AR4、 AR5由调用函数保护,在被调用函由调用函数保护,在被调用函数中可以自由使用且不必恢复。数中可以自由使用且不必恢复。 (2)堆栈指针)堆栈指针SP在函数调用时必须保护,但它是自动保护的。在函数调用时必须保护,但它是自动保护的。(3)ARP 在函数进入和返回时,必须为在函数进入和返回时,必须为0,即当前辅助寄存器,即当前辅助寄存器为为AR0。函数执行时可以为其他值。函数执行时可以为其他值。1.TMS320C54x DSP中寄存器规则中寄存器规则(4 4)在默认的情况下,编译器总是认为)在默认的情况下,编译器总是认为ST1ST1中的中的OVMOVM为为0 0。因此,。因此
20、,若在汇编程序中将若在汇编程序中将OVMOVM置为置为1 1,则返回,则返回C/C+C/C+环境时,必须将其恢环境时,必须将其恢复为复为0 0。(5 5)在默认的情况下,编译器总是认为)在默认的情况下,编译器总是认为CPLCPL为为1 1。因此,若在汇。因此,若在汇编程序中将编程序中将CPLCPL清清0 0,则在返回,则在返回C/C+C/C+环境时,必须将其恢复为环境时,必须将其恢复为1 1。(6 6)寄存器变量寄存器变量 编译器为两个寄存器关键字声明的变量分配寄编译器为两个寄存器关键字声明的变量分配寄存器,第一个变量必须声明为存器,第一个变量必须声明为AR1,AR1,第二个变量必须声明为第二
21、个变量必须声明为AR6AR6,其顺序不能改变。其顺序不能改变。变量必须声明为全局变量,必须在变量列表和变量必须声明为全局变量,必须在变量列表和函数语句的第一块中声明。函数语句的第一块中声明。 其他状态位和寄存器在子程序中可以任意使用,不必将其恢其他状态位和寄存器在子程序中可以任意使用,不必将其恢复。复。寄存器使用和保护规则寄存器寄存器用途用途由被调用函数保护由被调用函数保护由调用函数保护由调用函数保护AR0指针和表达式指针和表达式不是不是是是AR1指针和表达式指针和表达式是是不是不是AR2AR5指针和表达式指针和表达式不是不是是是AR6指针和表达式指针和表达式是是不是不是AR7指针、表达式和结
22、构指指针、表达式和结构指针针是是不是不是A表达式,传递第一个参表达式,传递第一个参数给函数,返回函数给函数,返回函数值数值不是不是是是B表达式表达式不是不是是是SP堆栈指针堆栈指针不是不是是是T乘法和移位表达式乘法和移位表达式不是不是是是ST0,ST1状态寄存器状态寄存器见表见表2见表见表2BRC块重复寄存器块重复寄存器不是不是是是表2 状态寄存器字段描述字段字段字段名称字段名称状态位值状态位值修改修改ARP辅助寄存器指针辅助寄存器指针0可以可以ASM累加器移位累加器移位可以可以BRAF块循环标志块循环标志不可以不可以C进位标志进位标志可以可以C16双双16位标志位标志0不可以不可以CMPT兼
23、容方式选择兼容方式选择0不可以不可以CPL编译方式选择编译方式选择1不可以不可以FRCT小数方式选择小数方式选择0不可以不可以OVA累加器累加器A溢出标志溢出标志可以可以OVB累加器累加器B溢出标志溢出标志可以可以OVM溢出方式位选择溢出方式位选择0只能在内部修改只能在内部修改SXM符号扩展方式选择符号扩展方式选择可以可以SMUL饱和方式选择饱和方式选择0只能在内部修改只能在内部修改SST饱和方式存储饱和方式存储0不可以不可以TC测试位标准测试位标准可以可以,2.TMS320C54x DSP中函数调用规则中函数调用规则(1)参数传递)参数传递 函数调用前,将参数以逆序压入运行堆栈,即最右边的参
24、数函数调用前,将参数以逆序压入运行堆栈,即最右边的参数最先入栈,然后自右向左将参数依次入栈。但是,对于最先入栈,然后自右向左将参数依次入栈。但是,对于TMS320C54X,在函数调用时,第一个参数放入累加器,在函数调用时,第一个参数放入累加器A中进行传递。若参数是长整型和浮点数时,则低位字先压中进行传递。若参数是长整型和浮点数时,则低位字先压栈,高位字后压栈。若参数中有结构形式,则调用函数给栈,高位字后压栈。若参数中有结构形式,则调用函数给结构分配空间结构分配空间,其地址通过累加器其地址通过累加器A传递给被调用函数。传递给被调用函数。函数调用时堆栈的使用如下所示:函数调用时堆栈的使用如下所示:
25、 函数调用规则包括:函数调用规则包括:返回地址PC函数参数2函数参数3SPSP+1SP+2堆栈堆栈函数参数函数参数1累加器累加器A高地址高地址低地址低地址(2)局部帧的产生)局部帧的产生每调用一个函数,就建立一个当前函数帧每调用一个函数,就建立一个当前函数帧 。C环境环境利用该帧保护调用者的有关信息、传递参数和生利用该帧保护调用者的有关信息、传递参数和生成局部变量块。成局部变量块。在在C语言中调用汇编语言编写的子程序,主要应弄语言中调用汇编语言编写的子程序,主要应弄清楚堆栈的使用情况,特别注意这里使用的堆栈清楚堆栈的使用情况,特别注意这里使用的堆栈不是不是DSP的硬件堆栈,而是的硬件堆栈,而是
26、.cmd文件定义的软堆文件定义的软堆栈。栈。TMS320C54x中调用函数时堆栈的使用情况中调用函数时堆栈的使用情况(3)函数的返回)函数的返回 如果被调用函数修改了寄存器如果被调用函数修改了寄存器AR1,AR6和和AR7,则必须予以恢复。则必须予以恢复。函数的返回值保存在累加器函数的返回值保存在累加器A中。整数和指针在累加器中。整数和指针在累加器A的低的低16位中返回;浮位中返回;浮点数和长整型数在累加器点数和长整型数在累加器A的的32位中返回;如果位中返回;如果函数返回一个结构体,则被调用函数将结构体的函数返回一个结构体,则被调用函数将结构体的内容拷贝到累加器内容拷贝到累加器A所指向的存储
27、器空间;如果所指向的存储器空间;如果函数没有返回值,则函数没有返回值,则A置置0。(1)函数如何调用)函数如何调用函数(调用者)在调用被调用函数时执行以下任务:函数(调用者)在调用被调用函数时执行以下任务:n调用者将第一个(最左边)的参数值放进累加器调用者将第一个(最左边)的参数值放进累加器A。调。调用者将剩下的参数按自右向左的顺序传进参数块,剩下的用者将剩下的参数按自右向左的顺序传进参数块,剩下的最左边的参数在最低的地址。最左边的参数在最低的地址。n若函数返回一个结构,则调用者为该结构分配空间,然若函数返回一个结构,则调用者为该结构分配空间,然后用累加器后用累加器A传递返回空间的地址给被调用
28、的函数。传递返回空间的地址给被调用的函数。n调用者调用函数。调用者调用函数。 (2)被调用函数如何响应)被调用函数如何响应被调用函数执行以下任务:被调用函数执行以下任务:n注意:如果被调用函数是注意:如果被调用函数是C/C+函数,则下面步骤都是由汇编器自动函数,则下面步骤都是由汇编器自动完成。如果被调用函数是汇编函数,则:完成。如果被调用函数是汇编函数,则:若被调用函数要修改若被调用函数要修改AR1,AR6或或AR7,则首先将他们压入堆栈。,则首先将他们压入堆栈。被调用函数通过从被调用函数通过从SP减去一个常数,为自身局部变量块和局部参数块减去一个常数,为自身局部变量块和局部参数块分配存储器。
29、该常数按以下公式计算,即:分配存储器。该常数按以下公式计算,即: 局部变量块的大小局部参数块的大小局部变量块的大小局部参数块的大小padding padding值是为了保证值是为了保证SP对准偶数边界而可能要求补充的一个字,对准偶数边界而可能要求补充的一个字,padding为为1或或0 。之所以。之所以SP要对准偶数边界,是因为要对准偶数边界,是因为5000系列系列DSP指令可一次读写存储器的指令可一次读写存储器的32 b,例如,例如DLD,DADD等。这样,编译器等。这样,编译器必须保证所有必须保证所有32 b的目标都驻留在偶数边界。对于混合编程而言可以的目标都驻留在偶数边界。对于混合编程而
30、言可以在汇编函数中,按本步骤的方法在堆栈中分配局部帧,但本方法相对在汇编函数中,按本步骤的方法在堆栈中分配局部帧,但本方法相对比较麻烦,尤其该汇编函数还要调用其他函数时,所以,比较麻烦,尤其该汇编函数还要调用其他函数时,所以,一般而言编一般而言编程者通常用其他方法分配局部帧,比如用程者通常用其他方法分配局部帧,比如用.bss伪指令定义局部变量供伪指令定义局部变量供函数使用。函数使用。被调用函数执行函数中的应用代码。被调用函数执行函数中的应用代码。 若被调用函数返回一个值,则被调用函数将该值放在累加若被调用函数返回一个值,则被调用函数将该值放在累加器器A中;若被调用函数返回一个结构,则被调用函数
31、将该中;若被调用函数返回一个结构,则被调用函数将该结构复制到累加器结构复制到累加器A指到的存储器块;若调用者不返回函指到的存储器块;若调用者不返回函数值,则数值,则A被置被置0。被调用函数给被调用函数给SP上加上第二步计算的常数,释放为局部上加上第二步计算的常数,释放为局部变量和局部参数分配的存储空间。对混合编程而言,如果变量和局部参数分配的存储空间。对混合编程而言,如果编程者没有在堆栈中分配局部帧,则本步骤省略。编程者没有在堆栈中分配局部帧,则本步骤省略。被调用函数恢复所有保存的寄存器。被调用函数恢复所有保存的寄存器。被调用函数执行返回。被调用函数执行返回。汇编语言被调用函数的例子:汇编语言
32、被调用函数的例子: callee: ;函数入口;函数入口 PSHM AR6 ;存;存AR6 PSHM AR7 ;存;存AR7 FRAME #-15 ;分配函数体框架参数;分配函数体框架参数 ;函数体;函数体 FRAME #15 ;分配函数体框架参数;分配函数体框架参数 POPM AR7 ;恢复;恢复AR7 POPM AR6 ;恢复;恢复AR6 RET ;返回;返回n在编写独立的汇编程序时,必须注意以下几点:在编写独立的汇编程序时,必须注意以下几点:(1)不论是用)不论是用C语言编写的函数还是用汇编语言编语言编写的函数还是用汇编语言编写的函数,写的函数,都必须遵循寄存器使用规则都必须遵循寄存器使
33、用规则。(2)必须保护函数要用到的几个特定寄存器。)必须保护函数要用到的几个特定寄存器。 (3)中断程序必须保护所有用到的寄存器。)中断程序必须保护所有用到的寄存器。(4)从汇编程序调用)从汇编程序调用C函数时,第一个参数(最左函数时,第一个参数(最左边)必须放入累加器边)必须放入累加器A中,剩下的参数按自右向中,剩下的参数按自右向左的顺序压入堆栈。左的顺序压入堆栈。(5)调用)调用C函数时,注意函数时,注意C函数只保护了几个特定的函数只保护了几个特定的寄存器,而其他是可以自由使用的。寄存器,而其他是可以自由使用的。(6)长整型和浮点数在存储器中存放的顺序是低位)长整型和浮点数在存储器中存放的
34、顺序是低位字在高地址,高位字在低地址。字在高地址,高位字在低地址。(7)如果函数有返回值,返回值存放在累加器)如果函数有返回值,返回值存放在累加器A中。中。 (8)汇编语言模块不能改变由)汇编语言模块不能改变由C模块产生的模块产生的.cinit段,段,如果改变其内容将会引起不可预测的后果。如果改变其内容将会引起不可预测的后果。(9)编译器在所有标识符(函数名、变量名等)编译器在所有标识符(函数名、变量名等)前加下划线前加下划线“_”。 (10)任何在汇编程序中定义的对象或函数,如果)任何在汇编程序中定义的对象或函数,如果需要在需要在C程序中访问或调用,则必须用汇编指程序中访问或调用,则必须用汇
35、编指令令.global定义。定义。 (11)编辑模式)编辑模式CPL指示采用何种指针寻址,如果指示采用何种指针寻址,如果CPL=1,则采用堆栈指针则采用堆栈指针SP寻址;如果寻址;如果CPL=0,则选择页指针则选择页指针DP进行寻址。进行寻址。 例例1在在C语言中调用汇编语言函数语言中调用汇编语言函数nC程序:程序: Extern int asmfunc ( ); /*声明外部的汇编子程序声明外部的汇编子程序*/ /*注意函数名前不要加下划线注意函数名前不要加下划线*/ int gvar; /*定义全局变量定义全局变量*/ main( ) int i=3; gvar=asmfunc(i); /
36、*进行函数调用进行函数调用*/ n汇编程序:汇编程序: _asmfunc: ;函数名前一定要有下划线;函数名前一定要有下划线 ADD *(_ gvar),A ;加法结果存在;加法结果存在A中中 STL A,*( _ gvar) ;将;将A中的结果存到中的结果存到gvar RETD ;子程序返回;子程序返回返回本节例例2 用用C/C+编写的主程序调用汇编语言编写的编写的主程序调用汇编语言编写的32位乘法位乘法运算子程序。运算子程序。n虽然用虽然用C/C+语言表达语言表达32 b乘法运算较为方便和明了,乘法运算较为方便和明了,但由于但由于C/C+语言无法很好利用语言无法很好利用DSP汇编语言为实现
37、各汇编语言为实现各种乘法运算而提供的指令,而使得种乘法运算而提供的指令,而使得C/C+程序效率低下。程序效率低下。所以这里用汇编语言完成所以这里用汇编语言完成32 b乘法运算,再用乘法运算,再用C/C+程程序调用它。序调用它。n算法简介算法简介由于由于16 b定点定点DSP中没有中没有32 b乘法指令,所以一定要用几乘法指令,所以一定要用几种种16 b乘法指令结合一定算法来进行乘法指令结合一定算法来进行32 b乘法运算。一乘法运算。一个个32 b数在存储器中是分开存储的。高数在存储器中是分开存储的。高16位存放在低地位存放在低地址,它在进行乘法运算是可以看作一个址,它在进行乘法运算是可以看作一
38、个16 b有符号数;有符号数;低低16位存放在相邻的低地址,他进行乘法运算时可以看位存放在相邻的低地址,他进行乘法运算时可以看作一个作一个16 b无符号数。于是算式如下:无符号数。于是算式如下:其中:其中:S代表符号数;代表符号数;U代表无符号数。代表无符号数。由上算式可见,在由上算式可见,在32 b乘法运算中,实际上包含了乘法运算中,实际上包含了3种乘法运算:种乘法运算:U*U,S*U和和S*S 。一般的乘法运算指令都是两个带符号数相乘,即。一般的乘法运算指令都是两个带符号数相乘,即S*S。所以在。所以在编程时,还要用到以下两条乘法指令:编程时,还要用到以下两条乘法指令:#include #
39、includeint main( )extern int *MPY32(long X32, long Y32) ;声明外部的声明外部的32b乘法运算汇编子程序,该函数返回指针值乘法运算汇编子程序,该函数返回指针值int w4int *pint ip=MPY32(0 x11112222,0 x33334444) ;进行函数调用进行函数调用;该指针指向数据存储器中,存放相乘结果单元的首地址;该指针指向数据存储器中,存放相乘结果单元的首地址for(i=0;i4;i+)wi=*p+ ;将乘法结果存到数组中将乘法结果存到数组中printf(“%xn”,Wi) ;以十六进制方式输出该数组值以十六进制方式输
40、出该数组值举例:C语言主程序语言主程序 在主程序中进行在主程序中进行MPY32函数调用时,函数传递情形如图函数调用时,函数传递情形如图2所所示。函数示。函数MPY32的第一参数存放在的第一参数存放在A累加器中,第二个参累加器中,第二个参数在堆栈中,高数在堆栈中,高16位在堆栈中的低地址,低位在堆栈中的低地址,低16位在堆栈位在堆栈中的高地址。由于中的高地址。由于MPY32是汇编语言函数,所以编译器是汇编语言函数,所以编译器不为其分配局部帧,局部帧的分配在汇编程序中进行。不为其分配局部帧,局部帧的分配在汇编程序中进行。汇编语言函数汇编语言函数:.mmregs.bss x1,1 ;为局部帧分配内存
41、空间;为局部帧分配内存空间.bss x0,1.bss y1,1.bss y0,1.bss w3,1.bss w2,1.bss w1,1.bss w0,1.text.global _MPY32 ;声明函数名为全局变量声明函数名为全局变量STM #X1,AR2 ;令令AR2指向第一个参数存放单元指向第一个参数存放单元STM #Y1,AR3 ;令令AR3指向第二个参数存放单元指向第二个参数存放单元STM #W0,AR4 ;令令AR4指向乘法结果存放单元指向乘法结果存放单元STH, A,*AR2+ ;传递第一个参数传递第一个参数STL, A,*AR2 LD *SP(1), A ;传递第二个参数传递第二
42、个参数STH A, *AR3+ LD *SP(2), A STL, A,*AR3LD #00, ALD *AR2, T ;T=x0_MPY32:MPYU *AR3-, A ;A= ux0*uy0STL A, *AR4- ;w0=ux0*uy0LD A,-16, AMACSU *AR2-, *AR3+, A ; A+=y1*ux0MACSU *AR3-, *AR2, A ;A+=x1*uy0STL A, *AR4- ;w1=ALD A, -16, AMAC *AR2,*AR3,A ;A+=x1*y1STL A, *AR4- ;为;为W2赋值赋值STH A, *AR4 ;为;为W3赋值赋值LD W
43、3, A ;将将W3单元地址作为返回值,传递到单元地址作为返回值,传递到A累累加器加器RET汇编程序可以看出,在汇编程序中至少要为局部帧分配汇编程序可以看出,在汇编程序中至少要为局部帧分配8个单元,个单元,其中其中4个单元用来存放参数值,个单元用来存放参数值,4个单元用来存放运算结果个单元用来存放运算结果 从从C程序中访问在汇编程序中定义的变量或常数,根据变程序中访问在汇编程序中定义的变量或常数,根据变量所在的位置和属性,可以分为以下量所在的位置和属性,可以分为以下3种情况:种情况:(1)访问在)访问在.bss块中定义的变量块中定义的变量 实现方法如下:实现方法如下:用用.bss或或.usec
44、t伪指令定义变量伪指令定义变量用用.global伪指令定义外部变量伪指令定义外部变量汇编语言中在变量名前加下划线汇编语言中在变量名前加下划线在在C中将变量定义成外部的,然后用普通的方式访问。中将变量定义成外部的,然后用普通的方式访问。采用上述方法后,在采用上述方法后,在C程序中就可以访问这个变量程序中就可以访问这个变量6.3.2 从从C程序中访问汇编程序变量程序中访问汇编程序变量例:例:汇编语言程序:汇编语言程序:/注意变量名前都有下划线注意变量名前都有下划线 .bss _var,1 ;.bss _var,1 ;定义变量定义变量 .global _var ;.global _var ;说明为外
45、部变量说明为外部变量C C语言程序:语言程序: extern int var; / extern int var; /* *外部变量外部变量* */ / var=1; /var=1; /* *访问变量访问变量* */ /(2)访问不在)访问不在.bss块中定义的变量块中定义的变量 不希望变量定义在不希望变量定义在.bss段,例如一个在汇编语言中定义段,例如一个在汇编语言中定义的数据表,不希望将它存放在的数据表,不希望将它存放在RAM中。在这种情况中。在这种情况下,必须定义一个指针指向对象,然后在下,必须定义一个指针指向对象,然后在C程序中间程序中间接访问它。所需的操作如下:接访问它。所需的操作
46、如下:n定义对象,最好将其放入一个独立的初始化段中。定义对象,最好将其放入一个独立的初始化段中。n声明一个全局标号,指向对象的起始地址。这样对象声明一个全局标号,指向对象的起始地址。这样对象可以被连接到存储空间的任意位置。可以被连接到存储空间的任意位置。n在在C程序中,将标号声明为外部的,不要在标号前加程序中,将标号声明为外部的,不要在标号前加下划线。下划线。n在在C程序中,定义一个指针变量指向该对象。这样做程序中,定义一个指针变量指向该对象。这样做之后就可以正常地访问该对象了之后就可以正常地访问该对象了以以C程序访问汇编程序中数据表为例。程序访问汇编程序中数据表为例。汇编语言:汇编语言: .
47、global _sine ;定义指向该表起始的全局符号定义指向该表起始的全局符号 .sect “sine_tab” ;定义一个独立的段定义一个独立的段_sine: ;表起始地址;表起始地址 .float 0.0 .float 0.015987 .float 0.022145C语言程序:语言程序: extern float sine ; /*声明外部数组声明外部数组*/ float *sine_p=sine; /*定义一个指针变量指向该数据表定义一个指针变量指向该数据表*/ f=sine_p4; /*访问访问sine_p*/(3)C程序中访问汇编程序中的常量程序中访问汇编程序中的常量一般情况下,
48、汇编中的常量在一般情况下,汇编中的常量在C程序中也定义为同样的程序中也定义为同样的常量,从而避免在常量,从而避免在C程序中访问汇编程序中的常量。程序中访问汇编程序中的常量。对于对于在汇编程序中用在汇编程序中用.set和和.global伪指令定义的全局常伪指令定义的全局常数数,也可以使用特殊的操作从也可以使用特殊的操作从C程序中访问它们。程序中访问它们。在在汇编中定义的常数,符号表包含的是常数的值汇编中定义的常数,符号表包含的是常数的值,C中中定义的变量,符号表实际上包括的是变量值的地址,定义的变量,符号表实际上包括的是变量值的地址,而非变量值本身而非变量值本身。但编译器不会区分符号表中的数值但
49、编译器不会区分符号表中的数值与地址。如果按常量名访问,得到的将是地址为常量与地址。如果按常量名访问,得到的将是地址为常量的存储单元的数值。为了避免这种情况的出现,必须的存储单元的数值。为了避免这种情况的出现,必须用用&运算符来得到常量值。所以在运算符来得到常量值。所以在C中访问汇编中的中访问汇编中的常数常数_x,应在常数名前加一个地址操作符为,应在常数名前加一个地址操作符为“&x”例:汇编语言程序例:汇编语言程序: _table_size .set 10000 ;定义常量定义常量 .global _table_size ;定义为全局变量;定义为全局变量C语言程序:语言程序:ex
50、tern int table_size /*声明外部变量声明外部变量*/#define TABLE_SIZE (int)(&table_size) /*用地址符号指用地址符号指明变量明变量*/ for(i=0; i TABLE_SIZE; i +) /*正常使用符号正常使用符号*/6.3.3 在在C程序中直接嵌入汇编语句程序中直接嵌入汇编语句n在在C程序中嵌入汇编语句是一种直接的程序中嵌入汇编语句是一种直接的C模块和汇模块和汇编模块接口方法。采用这种方法一方面可以在编模块接口方法。采用这种方法一方面可以在C程序中实现用程序中实现用C语言难以实现的一些硬件控制功语言难以实现的一些硬件控制
51、功能。另一方面,也可以用这种方法在能。另一方面,也可以用这种方法在C程序中的程序中的关键部分用汇编语句代替关键部分用汇编语句代替C语句以优化程序。语句以优化程序。n采用这种方法的一个缺点是它比较容易破坏采用这种方法的一个缺点是它比较容易破坏C环环境,因为境,因为C编译器在编译嵌入了汇编语句的编译器在编译嵌入了汇编语句的C程序程序时并不检查或分析所嵌入的汇编语句。时并不检查或分析所嵌入的汇编语句。n嵌入汇编语句的方法嵌入汇编语句的方法比较简单,只需在汇编语句的两边加上比较简单,只需在汇编语句的两边加上括号和双引号,并且在括号前加上括号和双引号,并且在括号前加上asm标识符标识符即可,即即可,即asm(“汇编语句汇编语句”)。n但是,采用此种方法必须但是,采用此种方法必须注意以下几点:注意以下几点: 括号中的汇编语句必须以标号、空格、括号中的汇编语句必须以标号、空格、tab、分号、分号开头,这和通常的汇编编程的语法一样。开头,这和通常的汇编编程的语法一样。 不要破坏不要破坏C环境,因为环境,因为C编译器并不检查和分析嵌编译器并不检查和分
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 地下管线工程质量通病预防措施
- 幼儿园传染病隔离措施执行要点
- 中考生物二轮复习教案专题五《生物的生殖发育》
- 电力设备安装关键工序及重要部位的质量控制措施
- 港口码头减少噪音与污染技术措施
- 文物保护措施在城市规划中的融入
- (2025年标准)技术项目转让协议书
- (2025年标准)激励奖励协议书
- 装饰装修工程造价咨询风险防范措施
- 钢铁冶炼厂有限空间较大危险因素辨识与主要防范措施
- 腰椎间盘突出症的中医治疗及护理课件
- 安徽省合肥市一中、六中、八中2024届数学高一上期末学业质量监测模拟试题含解析
- 电子对抗原理与技术-计算题参考答案
- 外研版初中英语单词总表(7~9)年级
- 大众文化概论-课件
- 商业装修手册
- 医院信息互联互通化成熟度测评
- 股票k线图入门图解
- GB/T 15812.1-2005非血管内导管第1部分:一般性能试验方法
- 无轨运输安全操作规程
- 专升本英语统考试翻译技巧课堂教学课件2
评论
0/150
提交评论