打印

keil函数参数传递能否定位到idata?

[复制链接]
7328|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
acmilann|  楼主 | 2008-6-2 11:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
keil函数参数传递能否定位到idata?
我们都知道C51中参数传递方法:
1,通过寄存器组传递参数,调用函数把参数传入寄存器组里,在被调用函数里还要把参数从寄存器组里存入固定存储地址。

2,通过固定存储区传递参数,调用函数直接把参数传入固定的存储地址里,被调用函数从这里取参数就是了。

3,通过模拟栈传递参数.

我写了很多函数,参数也都比较多,所以函数的参数传递基本上是通过固定存储区传递,但是通过固定存储区传递只能靠编译模式选择small、compact、large。也就是说只能定位到data、pdata、xdata区域中。




现在的问题是想把参数传递定位到idata区域中,不知有没有办法做到?



相关帖子

沙发
ayb_ice| | 2008-6-2 14:36 | 只看该作者

可以到PDATA,XDATA

IDATA可以试试
比如:void delay(char idata i);

使用特权

评论回复
板凳
acmilann|  楼主 | 2008-6-2 16:54 | 只看该作者

这种方式没用的

void delay(char idata i);
这种方式是没用的,我早就试过。

使用特权

评论回复
地板
ayb_ice| | 2008-6-2 20:21 | 只看该作者

随便说说

#pragma SAVE

#pragma NOREGPARMS    // 有点不大记得怎么写(不使用寄存器传递参数)

void delay(char a)
{
    a = a;
}

#pragma REGPARMS    // 有点不大记得怎么写(使用寄存器传递参数)

// 注意函数声明也要使用#pragma NOREGPARMS这些,这样使用直接地址DATA传递参数,当然也可以当作IDATA。。。

使用特权

评论回复
5
acmilann|  楼主 | 2008-6-2 20:39 | 只看该作者

这样好像也是按存储模式来的吧

这样只是不用寄存器传递,还是无法定位到idata中。

浪费了idata区感觉好可惜

使用特权

评论回复
6
ayb_ice| | 2008-6-2 21:01 | 只看该作者

也可以控制每个函数的编译模式

没有直接的方法,就好象C里不能直接操作寄存器一样。
你这是用KEIL,其它编译器根本没有这么多东东。

使用特权

评论回复
7
xwj| | 2008-6-2 21:20 | 只看该作者

好钢用在刀刃上,LZ没听说过这句话吗?

首先,你要明白用idata绝对会比用其他方式慢(自己去想想),
然后,要知道参数区肯定是能做覆盖分析的哦,你想传多少参数?你想嵌套多少次?一次参数多的话为什么不用指针???


就为了那省不掉而且能覆盖的几个公用内存单元而严重影响每个函数的调用效率???

使用特权

评论回复
8
ayb_ice| | 2008-6-2 21:22 | 只看该作者

我就不说了

使用特权

评论回复
9
acmilann|  楼主 | 2008-6-2 22:27 | 只看该作者

回复七楼的

现在是要写一个库函数给客户用,这个库函数的每个函数并不一定被客户用到,但包含这个lib的工程在small模式下编译是通不过的。只能到compact或large模式编译。如果我将库函数的变量,参数传递全都定位到idata中去,这样客户的程序就能在small模式编译,不是比我在large模式下要优化一点。
在所有的数据区间里idata是仅次于data的区间。

使用特权

评论回复
10
alongman| | 2008-6-2 23:05 | 只看该作者

那就试一下全局变量吧.

使用特权

评论回复
11
xwj| | 2008-6-2 23:26 | 只看该作者

唉,你还是没搞清楚应该优化什么...

使用特权

评论回复
12
wxj1952| | 2008-6-3 00:20 | 只看该作者

很简单。

如果要将整个程序的局部变量或者全局变量定位到Idata空间,只要在“Project/options for Target/BL51 Locate/Idata 栏内键入段名和起始地址。段名规则按keil C51规则:例如模块test.c,全局变量定位在idata 90h:?DT?test(90h)。函数func(idata int )定位假定idata 0a0h:在Idata栏键入 ?DT?_func?test(0a0h)。

xwj说的值得重视,idata区只能间接寻址,这样以时间换空间也许是好主意。但是这样做就会把堆栈区推到idata 最后,除非你肯定堆栈不会溢出。

另外好像连接/定位器能够自动管理好全局和局部变量Idata区,说不好,也许是要人工助力,仔细分析吧。注意调试状态下:data区观察用d:00。idata区观察用i:00。

使用特权

评论回复
13
wxj1952| | 2008-6-3 08:57 | 只看该作者

简单化一点。

LS 搞复杂了。其实只要在“Project/options for Target/BL51 Locate/Idata 栏的“BASE”基地址栏内键入0x80,就把Idata段定位到了高128字节。这样你在程序中的所有 idata 修饰变量,都自动定位到了RAM高128字节区域。由编译器/连接器自动管理。

***************************************************************

void delay(char idata i);
这种方式是没用的,我早就试过。

 ayb_ice 说的void delay(char idata i); 是对的,你之所以认为没用,是你概念没弄清,认为低128字节RAM是 data 区而不是 idata 区。提醒一下:低128字节既是 data 又是 idata 区!不信你定义一个idata char matrix[128];数组,然后将其初始化为0,1,2,3,.....127, 实验看看结果;修改成 data int matrix[128];能行吗?

还有此时堆栈由C51定位到了那里?

使用特权

评论回复
14
ayb_ice| | 2008-6-3 09:28 | 只看该作者

都说了,每个函数可以定义编译模式

那这还有什么问题

使用特权

评论回复
15
acmilann|  楼主 | 2008-6-3 11:33 | 只看该作者

回复wxf1952

不知是我没说清楚还是你没看明白?
void delay(char idata i);
中的i是不会被定义到idata中,不管是高128,还是低128.应为这里的i是一个形参,不是一个变量。编译器是按照参数传递的规则来分配地址。
就对这个函数而言i就是R7。
如果是如下函数
 void delay(char idata i,char idata j,char idata x,char idata z);

i,j,x对应R7,R5,R3。而z定位在哪里就看编译模式可以在data、pdata、xdadt中

我现在想通过设置将z自动定位到idata中,但是找不到方法

使用特权

评论回复
16
acmilann|  楼主 | 2008-6-3 11:48 | 只看该作者

更直白一点,如何w定位到idata中

在small模式下          idata修饰不起作用
     
     4: char max(char  x,char  y,char   z,char idata  w )  
     5: { 
     6:  
     7:             return (x+y+z+w); 
     8:  
C:0x083D    EF       MOV      A,R7
C:0x083E    2D       ADD      A,R5
C:0x083F    2B       ADD      A,R3
C:0x0840    2528     ADD      A,0x28                 ---w
C:0x0842    FF       MOV      R7,A

在compact模式下          idata修饰还是不起作用
     4: char max(char  x,char  y,char   z,char idata  w ) 
     5: { 
     6:  
     7:             return (x+y+z+w); 
     8:  
C:0x084B    EF       MOV      A,R7
C:0x084C    2D       ADD      A,R5
C:0x084D    2B       ADD      A,R3
C:0x084E    FF       MOV      R7,A
C:0x084F    7807     MOV      R0,#0x07
C:0x0851    E2       MOVX     A,@R0
C:0x0852    2F       ADD      A,R7
C:0x0853    FF       MOV      R7,A

在large模式下          idata修饰还是不起作用
     4: char max(char  x,char  y,char   z,char idata  w ) 
     5: { 
     6:  
     7:             return (x+y+z+w); 
     8:  
C:0x0875    EF       MOV      A,R7
C:0x0876    2D       ADD      A,R5
C:0x0877    2B       ADD      A,R3
C:0x0878    FF       MOV      R7,A
C:0x0879    900006   MOV      DPTR,#0x0006            -----w
C:0x087C    E0       MOVX     A,@DPTR
C:0x087D    2F       ADD      A,R7
C:0x087E    FF       MOV      R7,A

使用特权

评论回复
17
acmilann|  楼主 | 2008-6-3 12:28 | 只看该作者

回复四楼

#pragma NOREGPARMS    // 有点不大记得怎么写(不使用寄存器传递参数)
这样所有的参数都跟编译模式相关,但不能定位到idata中

使用特权

评论回复
18
ayb_ice| | 2008-6-3 14:40 | 只看该作者

无语了

都说了,可以单独控制每个函数的编译模式。。。

使用特权

评论回复
19
acmilann|  楼主 | 2008-6-3 16:24 | 只看该作者

控制编译模式能到idata去吗?

楼上的每个函数单独控制编译模式我知道。但是不能定位到idata。

使用特权

评论回复
20
ayb_ice| | 2008-6-3 16:26 | 只看该作者

small模式的DATA难道不可以当做IDATA

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

123

帖子

0

粉丝