9079|10

61

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

初学DSP 汇编问题(参数传递) [复制链接]

刚入手DSP汇编,想编个简单的测试程序运行下,功能是:主函数中用C,调用汇编文件中的功能函数两数相乘

编译出错: [E0002] Illegal mnemonic specified,下面是2个源文件,请帮看下,谢谢!

/*********main.c************/

#include <stdio.h>

void main()

{

    int m,n,a;

    m = 10;

    n = 20;

    a = MPY1(m, n);

    printf("a=%d \n",a);

}

/**********test.asm********/

     .text

    ..globle _MPY1

 

_MPY1:

    .asg A0, A_m

    .asg A2, A_n;

 

   MV  .S1  A0, A6

   MV  .S1  A2, A4

 

  LD  .D1 *A4, A3

  LD  .D1 *A6, A5

 

    MPY .M1 A3, A5, A7

    NOP 2

    .end

 

 

上面就是源程序了,第一次写,也不知道该怎么传递参数m,n。。。哪位兄弟出来帮解答下

 

[ 本帖最后由 breeze505 于 2012-4-25 11:06 编辑 ]

最新回复

1. Parent的意思是该寄存器由主函数(父函数)保存,除了Special Uses中指出的用处之外,在子函数中还可以用作中间变量;如果父函数是C函数,那么保存寄存器值的这步动作已经由编译器完成。 Child的意思是指如果在子函数中要修改该寄存器,必须由子函数保留该寄存器的值,并在子函数运行结束退出之前恢复,否则将破坏程序的runtime environment。 C与汇编混合编程,通常情况下,用汇编完成核心的、运算复杂的子函数,并由C程序调用之,所以在汇编代码中应注意Parent preserve的寄存器可以修改,Child preserve的寄存器必须先保存后再修改。 2. 你的代码中的问题在于MPY32指令有3个delay slot,其运算结果才生效。 修改如下(非优化繁琐版),仅供参考: #include extern void MPY1(int m, int n, int *r); int main() {     int m,n,r;     m = 10;     n = 20;     MPY1(m, n, &r);     printf("r=%d \n", r);     return 0; }     .text     .global _MPY1 _MPY1:     MV .S1 A4, A1     MV .S1x B4, A2     B .S2 B3     MPY32 .M1 A1, A2, A0     NOP 3     STW .D1 A0, *A6 ;   详情 回复 发表于 2012-4-26 15:53
点赞 关注
 

回复
举报

54

帖子

0

TA的资源

一粒金砂(高级)

沙发
 

回复 楼主 breeze505 的帖子

根据你的代码,估计你用的是c6000,参考spru187的第8章Run-Time Environment。

第一、二个参数分别用A4,B4,从你的代码看,调用汇编子函数是值传递,为什么又要把参数当成指针来用?
 
 

回复

61

帖子

0

TA的资源

一粒金砂(高级)

板凳
 

回复 沙发 carrotchen 的帖子

我的板子是c674x,
1. 是不是所有的参数都是用A4,B4来传递接收?那如果是3个参数呢?该怎么传?
2. 如你所说,我把代码改成下面,编译还是一样出错啊,求教!
   .text
     .globle _MPY1
  _MPY1:
    .asg A4, A_m
    .asg B4, A_n;

   MV  .S1  A4, A5
   MV  .S2  B4, A5

  LD .D1 A6,A5
  LD .D2 B6, B5

  MPY .M1 A5, B5, A7

  NOP 2
  .end
 
 
 

回复

54

帖子

0

TA的资源

一粒金砂(高级)

4
 

回复 板凳 breeze505 的帖子

1. 建议先看spru187的Table 8-2. Register Usage,参数怎么传,返回值怎么放,返回地址在哪,都有详细的说明。
2. 你的代码有问题:1) A4和B4已经是m和n的值,为什么用LD指令按照指针去取值? 2) _MPY1子函数未返回到主函数,.end就结束了?

以下代码(非优化繁琐版)仅作参考,对照spru187,spru732来看。
    .text
    .global _MPY1
_MPY1:
    B .S2 B3
    MV .S1 A4, A0
    MV .S1 B4, A1
    MPY32 .M1 A0, A1, A4
    NOP 2
    ; Branch

赞赏

1

查看全部赞赏

 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(高级)

5
 

回复 4楼 carrotchen 的帖子

感谢你的解答,我这没spru187文档。。有疑问请再帮指导下:

1. B .S2 B3 这条指令是干嘛?

2. 你的代码里程序通过什么返回回去?是通过A4?

3. 程序通过; Branch 结束?我试了下用.end也一样可以,

 4.我编译了你的代码,可以了!想再问下,如果我的程序参数传递想改成

 MPY1(m, n,a); 也就是把计算结果存在a中,这样的3个参数该怎么传?代码该怎么改,请指教

[ 本帖最后由 breeze505 于 2012-4-25 14:22 编辑 ]
 
 
 

回复

54

帖子

0

TA的资源

一粒金砂(高级)

6
 

回复 5楼 breeze505 的帖子

1. B .S2 B3,返回到主函数,B3是返回地址,在spru187中规定:http://www.ti.com/lit/ug/spru187o/spru187o.pdf
2. A4是子函数MPY1的返回值
3. ; Branch是注释,B .S2 B3是从子函数返回,但是B指令要延迟5个周期,在; Branch处生效,故标注之
4. 在CGT v6.1.20下可以通过,估计你的编译器较老,可以试做以下修改:
    .text
    .global _MPY1
_MPY1:
    B .S2 B3
    MV .S1 A4, A0
    MV .S1x B4, A1 ; <- S1改为S1x
    MPY32 .M1 A0, A1, A4
    NOP 2
    ; Branch

赞赏

1

查看全部赞赏

 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(高级)

7
 

回复 6楼 carrotchen 的帖子

感谢你的回复!
1. 是不是所有情况下,A4都接受函数的第一个参数?还有起返回值的作用?
2. 如果我要实现的是无返回值,如下:
void MPY1(int m, int n, int a)
{a = m + n;}
我改汇编代码如下:
.text
.global _MPY1
_MPY1:
.asg A4, m
.asg B4, n
.asg A3, a
B .S2 B3
MV .S1 A4, A0
MV .S1 B4, A1
MPY32 .M1 A0, A1, A3
NOP 2
; Branch
我编译了,执行结果不对,并没有写进去,应该是我不知道第三个参数怎么传?怎么写进a的计算结果值,请指教,谢谢!
 
 
 

回复

54

帖子

0

TA的资源

一粒金砂(高级)

8
 

回复 7楼 breeze505 的帖子

1. 如果是手工纯汇编,则大部分寄存器可任意使用(在C6000平台,手工纯汇编的难度很大,一般使用C+汇编或C+intrinsics的方式);如果代码是C和汇编混合编程,需要遵照spru187的寄存器规则:A4为第一个参数,子函数返回时保存返回值;B4是第二个参数;A6是第三个参数……具体参考Table 8-2. Register Usage

2. 当子函数要修改入参的值时,需要传指针,则函数原型应是:
void MPY1(int m, int n, int ×p_a)
{
*p_a = m + n;
}
那么p_a在A6中,需要把A6当成指针来使用。

赞赏

1

查看全部赞赏

 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(高级)

9
 

回复 8楼 carrotchen 的帖子

非常感谢!现在大概明白了参数的传递,但还有问题请教下:

1. 在Register Usage表里,A0-A9/B0-B9是Parent,A10-A15是Child的,这里是Parent和Child代表什么呢?是不是说Parent是用来传递参数,而Child是用来做函数里中间变量计算?

2. 按你的指导,我代码修改如下

 /*******main中*****/

void main()

 {

int n,m,result[2],tmp;

 m = 10;

n = 20;

tmp = MPY_1(m,n,result);

 printf("result=%d,tmp=%d",result[0],tmp);

}

/*****asm文件*****/

.text

 .global _MPY1

_MPY1:

 B .S2 B3

 MV .S1 A4, A0

 MV .S1 B4, A1

 MPY32 .M1 A0, A1, A7 ;m*n

STW .D1T1 A7, *+A6[0] ;把;m*n计算结果存到result中

MVK .S1 1, A4 ;返回1

NOP 2

 

但以上代码编译后执行结果:result = 0, tmp=1 为什么reslut不是想要得到的200呢,请帮忙看下

[ 本帖最后由 breeze505 于 2012-4-26 13:07 编辑 ]
 
 
 

回复

54

帖子

0

TA的资源

一粒金砂(高级)

10
 

回复 9楼 breeze505 的帖子

1. Parent的意思是该寄存器由主函数(父函数)保存,除了Special Uses中指出的用处之外,在子函数中还可以用作中间变量;如果父函数是C函数,那么保存寄存器值的这步动作已经由编译器完成。
Child的意思是指如果在子函数中要修改该寄存器,必须由子函数保留该寄存器的值,并在子函数运行结束退出之前恢复,否则将破坏程序的runtime environment。
C与汇编混合编程,通常情况下,用汇编完成核心的、运算复杂的子函数,并由C程序调用之,所以在汇编代码中应注意Parent preserve的寄存器可以修改,Child preserve的寄存器必须先保存后再修改。

2. 你的代码中的问题在于MPY32指令有3个delay slot,其运算结果才生效。
修改如下(非优化繁琐版),仅供参考:
#include

extern void MPY1(int m, int n, int *r);

int main()
{
    int m,n,r;
    m = 10;
    n = 20;
    MPY1(m, n, &r);
    printf("r=%d \n", r);
    return 0;
}

    .text
    .global _MPY1
_MPY1:
    MV .S1 A4, A1
    MV .S1x B4, A2
    B .S2 B3
    MPY32 .M1 A1, A2, A0
    NOP 3
    STW .D1 A0, *A6 ; <- MPY result is valid now
    ; <- Branch occurs

另外,可以尝试把MPY32指令替换为MPY指令(需1个delay slot),调整B指令的位置,修改NOP指令的延迟数,也能完成相同的功能。

赞赏

1

查看全部赞赏

 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(高级)

11
 

回复 10楼 carrotchen 的帖子

明白了,非常感谢!
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表