思路:由于对DSP的汇编语言确实不熟悉,并且没有找到c语言调用汇编语言的方法(只找到调用线性汇编的方法),所以采用c语言和汇编语言混合的形式来实现点乘累加算法的汇编语言,即在先c语言定义一个连续空间的整型数组(长度为10,因此B0的值也应该为10,即loop十次),然后手动找到对应数组的首地址,运行之后的汇编指令
①存储数据到存储器
如图1通过debug可以看到a数组和x数组的首地址分别为0x80001060,0x80001088(其实照理说编译器应该是自动分配数组地址的,但是一般是三次debug之后它才会分配另外一个地址)
②编写运行汇编指令代码
c语言和汇编混合代码如下:
#includeint main(void) { int a[10] = { 1,2,3,4,5,6,7,8,9,10 }; int x[10] = { 1,2,3,4,5,6,7,8,9,10 }; //printf("the x'add is %p,the a'add is%p",pt1,pt2); //sop_asm(pt1,pt2); // 这里的地址要根据上面两个数组的地址来写,寄存器会随机分配一段c6000存储器的地址, asm(" MVKL .S1 0x80001060, A5"); // 将低八位数据存入A5 asm(" MVKH .S1 0x80001060, A5"); // 将高八位数据存入A5 asm(" MVKL .S1 0x80001088, A6"); // 将低八位数据存入A6 asm(" MVKH .S1 0x80001088, A6"); // 将低八位数据存入A6 asm(" MVKL .S1 0x80002068, A7"); // 将低八位数据存入A7 asm(" MVKH .S1 0x80002068, A7"); // 将低八位数据存入A7 asm(" MVKL .S2 10, B0"); // 将立即数10存入B0 asm(" ZERO .L1 A4"); // 将A4清零 asm("LOOP: LDH .D *A5++[2],A0"); // 定义一个函数名LOOP;将A5这个寄存器存的地址+偏移量*2的对应数据拿出来放到A0种 asm(" LDH .D1 *A6++[2],A1"); // 定义一个函数名LOOP;将A6这个寄存器存的地址+偏移量*2的对应数据拿出来放到A0中 asm(" NOP 4"); // 转移指令的延迟间隙为4 asm(" MPY .M1 A0,A1,A3"); // A3=A0*A1 asm(" NOP 1"); // 乘法指令延迟间隙为1 asm(" ADD .L1 A4,A3,A4"); // A4=A3+A4 asm(" SUB .S2 B0,1,B0"); // B0=B0-1 asm(" [B0] B .S1 LOOP"); // 如果BO不为0,就跳转到LOOP这个函数 asm(" NOP 5"); // 跳转指令延迟间隙为5 asm(" STW .D1 A4, *A7"); // 将A4存的数据传到A7存的地址中(这个地址指向存储器) //sop_asm(); return 0; }
注意:
①运行普通指令的时候汇编指令需要空一格
②运行LOOP这种指令的时候需要定格
③严格按照延迟间隙来NOP,不然会出现错误
③观察地址空间数据变化
如图2只需观察四个寄存器的数值变化,第一个LOOP之后的值都改变成了1,第一个循环结束,A0,A1,A3,A4的数值皆为1,这里要注意的是由于我定义的数组为int类型,所占字节为4,因此LD指令寻址的时候需要乘以2
图2
如图3第二个loop我们则可以看到对应的数值变为2,2,4,5
如图4,等到第10个循环执行完后,数值分别为0x0000000A,0x0000000A,0x00000064,0x00000181,即最后结果为0x00000181(转化为10进制为385,符合两个数组皆为1-10的点乘累加结果),观察我们存储到地址为0x80002068的值也为0x00000181,即我们把最后结果模拟存到了c6000的数据存储器地址中(c6000的数据存储器的地址空间为80000000h~8003FFFh和80040000h~8007FFFFh)
2.2 c语言实现思路:c语言实现就比较简单了,主要思路是定义两个数组,然后把数组的首地址复制给一个指针循环取值相乘相加就行,最后的结果编译器应该会自动分配一个位于c6000的存储空间的一个地址给结果数据。
①数据存入存储空间
如图5此时编译器自动分配a和x的首地址分别为0x8000781C,0x80007830,最后y的存储地址为0x80007828,也在c6000的数据存储空间地址范围中,符合我们的模拟要求,
②c语言代码
③地址数据分析
如图5,在memory browser中我们可以看到最后y的存储地址为0x80007828,也在c6000的数据存储空间地址范围中,符合我们的模拟要求。
2.3 线性汇编语言实现思路:采用关键字extern声明的方式来声明线性汇编语言的函数入口,在c语言传实参调用线性汇编的指令,并把结果返回给c语言中,用printf打印结果
①工程目录
如上图,我们需要将c文件和sa文件放在同一个目录下
②代码实现
注意:这里和上面不同的是我把数组的定义改成了short为16个字节,所以下面的线性汇编的代码地址偏移量不需要乘以2了
main.c
sop.sa
③执行结果
如图6,我们可以看到线性汇编代码会帮我们自动分配寄存器给我们进行计算。
如图7为执行完毕的结果y的值为385,地址为0x80007850和我们用汇编语言和c语言实现的结果一样
3.实验总结总的来说,这次实验还是完成的比较艰难的,主要是c语言如何调用.asm汇编语言那里花了许多时间,百度了许久也没有找到好的方案,最后只能说是在c语言代码里面嵌入asm(“xxx”)语言来实现,(当然另外一种方法是直接先给寄存器赋值fill memery 但我没试过?)c语言和线性汇编实现的话就比较顺畅,当然我觉得这次实验更多了是熟悉了css这个编程平台,如何编译如何build如何debug,如何查看寄存器的值,如何查看存储器的值,这对我编写代码大有脾益。Ps:这辈子都不想再写汇编代码了。
我搜了全网作业都没有发现一个能直接运行的代码,要么格式很乱,要么格式不全,如果觉得我写的还不错的话请给一个赞吧!另外希望大家不要复制粘贴代码就不管了哦,还是得透过汇编代码来了解dsp的硬件结构!!!



