liang-s 发表于 2010-10-29 13:40:50

求助:ICCAVR函数入口地址问题

一直用ICCAVR,最近做一个小项目,需要在程序中获取某函数的入口地址,发现用“&”取函数地址,用“*”函数指针等等各种传统方法,获取的都不是真实的函数入口地址,但获取变量的地址就没问题,网上查了一整天,发现也有很多人发现了这个问题,据说是ICCAVR在处理函数地址以及函数指针时,返回的不是函数入口在SRAM中的实际地址,而是一个在SRAM中的“数据表”的地址,该“数据表”中存放的数据是各函数的入口地址,也就是说,用C的传统方法获取函数入口地址在ICCAVR中行不通(CVAVR,GCCAVR似乎没这问题?)。
请教高手来指点一下这个问题怎么解决?


例:

unsigned int TIME_Light=0xafaf; //背光计时器
unsigned int AQ_ADC[]=
{0xfcfc,0,0,0,0,0,0,0};//缓冲区

unsigned int Addr_A;
unsigned int Addr_B;
unsigned int Addr_C;
unsigned int Addr_D;




void port_init(void)
{
.....
}


void main (void)
{
......



}

void get_Addr (void)

{
Addr_A=(unsigned int)&TIME_Light;// 正确
Addr_B=(unsigned int)&AQ_ADC;      // 这两个获得正确的变量存放地址的两字节数据
Addr_C=(unsigned int)&port_init;   // 错误
Addr_D=(unsigned int)&main;      // 这两个获得的数据并非真实的函数入口地址数据
}

liang-s 发表于 2010-10-29 14:14:11

在线等,实在不想换编译器啊

biansf2001 发表于 2010-10-29 14:29:01

可以参考 菜单的做法
菜单里的函数调用

liang-s 发表于 2010-10-29 14:55:42

肯请LS详细说明,在ICCAVR中的实现方法。在标准C中那是地球人都知道。

lbc___ 发表于 2010-10-29 17:06:16

ICC 这个是有点问题,我也没完全搞懂,但是我有个方法解决。
比如你的函数名是Task();你可以这样处理:

temp_l = (unsigned char)((unsigned int)Task & 0xff);
temp_h = (unsigned char)((unsigned int)Task >> 8);
asm("LDS R30,%temp_l");
asm("LDS R31,%temp_h");
asm("LPM");
asm("STS %temp_l,R0");
asm("ADIW R30,0x01");
asm("LPM");
asm("STS %temp_h,R0");

之后temp_h和tamp_l里就是函数地址的高低字节了。
嵌入了汇编,但是要注意使用前把用到的寄存器入栈,用完后出栈。temp_h和tamp_l是unsigned char型的变量。

liang-s 发表于 2010-10-29 20:35:41

按楼上的办法写了一个函数:

unsigned int GET_funcAddr(unsigned char *funcName)
{

union AA
    {
       unsigned int temp_int;
       unsigned char temp;
       }Addr;


Addr.temp_int = (unsigned int)funcName;
temp_l=Addr.temp;
temp_h=Addr.temp;
//temp_l = (unsigned char)((unsigned int)funcName & 0xff);
//temp_h = (unsigned char)((unsigned int)funcName >> 8);

asm("PUSH R30");
asm("PUSH R31");
asm("PUSH R0");

asm("LDS R30,%temp_l");
asm("LDS R31,%temp_h");
asm("LPM");
asm("STS %temp_l,R0");
asm("ADIW R30,0x01");
asm("LPM");
asm("STS %temp_h,R0");

asm("POP R0");
asm("POP R31");
asm("POP R30");

Addr.temp = temp_l;
Addr.temp = temp_h;
return Addr.temp_int;

}


问题依旧,哎~~~ 是不是得换编译器了,我用的ICCAVR6.13

lbc___ 发表于 2010-10-31 20:38:41

回复【5楼】liang-s
-----------------------------------------------------------------------
这个我也不知道了
我用的icc7.1几 的,是可以的

azmrael 发表于 2011-5-13 00:51:42

我也遇到这问题,郁闷啊

millwood0 发表于 2011-5-13 01:01:46

why do you want to know the address of a function? what does knowing it do that you cannot achieve via other means, like a pointer to a function?

cwxdjh521 发表于 2011-5-13 02:04:16

Addr_C=(unsigned int)&port_init;   // 错误
~~~~~~~~~~~~~~~~
我的理解是这样的:
1.你的函数代码段是放在FLASH区域的;
2.而你的语法是引用RAM区域的内容

so 这个是不可能正常的。

其实在C语言中早就有函数指针的写法,你这样写是不符合规范的

你在百度中就可以授到得内容

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  int func(int x); /* 声明一个函数 */   
    int (*f) (int x); /* 声明一个函数指针 */   
    f=func; /* 将func函数的首地址赋给指针f */  

 赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。   注2:函数括号中的形参可有可无,视情况而定。   
   下面的程序说明了函数指针调用函数的方法:   
   例一、  
 #include<stdio.h>   
   int max(int x,int y)
      { return(x>y?x:y); }   
   
   void main()   
    {   
   int (*ptr)(int, int);   
   int a,b,c;   
      ptr=max;   
   scanf("%d,%d",&a,&b);   
   c=(*ptr)(a,b);   
   printf("a=%d,b=%d,max=%d",a,b,c);   
}

zend 发表于 2015-9-30 21:03:34

有方法了
unsigned int addr;
addr=*(unsigned int const *)_task1;
页: [1]
查看完整版本: 求助:ICCAVR函数入口地址问题