没那么简单!
在C51中调用A51函数,主要是A51的命名规则和参数传递规则必须符合C51的要求;下面我主要针对Franklin C51做一简要说明:
一、函数名转换规则;
C51程序模块编译成目标文件后,其中的函数名依据其定义的性质不同回转换为不同的函数名,其转换规则如下:
1、无参数传递或参数不通过寄存器传递的函数起函数名不做改变转入目标文件中;例如C51中申明的函数 void FunName(void),编译后名称为 FunName;
2、如果函数通过寄存器传递参数,则编译后在原函数名前加前缀"_";例如C51中申明的函数为:void FunName(char),编译后名称为:_FunName;
3、如果函数为包含堆栈内参数传递的可重入函数,则加前缀"_?";例如C51中申明的函数为:void FunName(void)reentrant,编译后名称为:_?FunName;
二、函数相关段命名规则;
一个C51源程序模块被编译后,其中的每一个函数以" ?PR?函数名?模块名 "为名的命名规则被分配到一个独立的CODE段。例如,如果模块“FUNC51”内包含一个名为“func”的函数,则其CODE段名为:“?PR?FUNC?FUNC51”。如果函数中包含有data和bit对象的局部变量,编译器将按“?函数名?BYTE”和"?函数名?BIT"命名规则建立一个data和bit段,他们代表所要传递参数的起始位置,其偏移值为0。这些段是公开的,因而它们可以被其他模块访问。另外这些段被赋予“OVERLAYABLE”标志,故可被连接/定位器作覆盖分析。A51和C51相互调用时,A51必须服从下列命名规则:
1、程序代码:段类型为CODE,则段名为:?PR?函数名?模块名(所有存储器模式);
2、局部变量:段类型为DATA,段名为:?DT?函数名?模块名(SMALL模式);段类型为PDATA,段名为:?PD?函数名?模块名(COMPACT模式);段类型为XDATA,段名为:?XD?函数名?模块名(LARGE模式);
3、局部bit变量:段类型为BIT,段名为::?BI?函数名?模块名(所有存储器模式);
三、参数传递规则;
Flanklin C51函数最多可以通过CPU寄存器传递3个参数,如果参数太多以至于寄存器不够用时,部分参数将在固定存储区内传递,这种混合情况非常不利于程序员编程,如果在源程序中选择了编译控制命令“#pragma NOREGPARMS”则所有参数传递都发生在固定存储区,存储区的地址空间依赖于所选择的存储器模式。
1、寄存器参数传递规则:第一个参数,如果是单字节变量就通过R7,双字节变量通过R6R7,4字节通过R4R5R6R7,一般指针通过R1R2R3; 第二个参数,单字节通过R5,双字节变量通过R4R5,4字节通过R4R5R6R7,一般指针通过R1R2R3; 第三个变量,单字节变量通过3,双字节通过R2R3,一般指针通过R1R2R3,不能传送4字节变量;
2、函数返回值的传递规则:布尔变量通过进位位C传递,其余类型的传递规则和第一个参数的传递规则相同。
例如:有一个A51程序为FunA51,要在C51中调用该函数,程序如下:
extern FunA51(unsigned char x, unsigned char y)
void main(void)
{
unsigned char R;
R=FunA51(0x12,0x32);
}
NAME MyA51 ;定义模块名
?PR?FunA51?MyA51 SEGMENT CODE ;FunA51代码段声明
PUBLIC _FunA51 ;公开函数名,以便C模块可以调用它, 因为函数有返回值故加了前缀"_"
RSEG ?PR?FunA51?MyA51
_FunA51:
MOV A, R7 ;第一个参数传递
MOV B, R5 ;第二个参数传递
DIV AB
MOV R7, A ;结果经R7返回
RET
END
以上是一个简单的说明,仅供参考,不足之处请多多指教,对于Keil C51不知道是不是这样就不得而知了.
发表时间:2003年7月25日10:39:25