新闻中心

EEPW首页>嵌入式系统>设计应用> Keil C51 中的函数指针和再入函数

Keil C51 中的函数指针和再入函数

作者: 时间:2016-11-27 来源:网络 收藏

本文引用地址://m.amcfsurvey.com/article/201611/322385.htm

函数指针的建议和技巧

有些函数指针的应用技巧。
使用指定空间的指针

把函数指针从一个普通的指针变成一个指定空间的指针。用一个字节保存指针。因为函数属于CODE存储区(在8051里),一个字节可以用来保存声明的函数指针作为CODE指针。例如:

void (code *function_ptr) (void) = another_function;

如果你选择在你的函数指针声明中包含code关键字,就可以在任何地方使用它。如果你声明一个函数,它接收一个3字节的普通指针,通过指定空间传递,2字节函数指针,坏事将要产生。

再入函数和指针

Keil C51 为函数的再入提供关键字“reentrant”。再入函数的参数通过模拟栈来传递。模拟栈对于small存储模式位于IDATA,对于compact存储模式位于PDATA,对于large存储模式位于XDATA。如果你使用再入函数,在STARTUP.A51中你必须初始化再入栈的指针。参考下面的启动代码:

;----------------------------------------------------------------------

;Reentrant Stack Initilization

;

;The following EQU statements define the stack pointer for reentrant

;functions and initialized it:

;

;Stack Space for reentrant functions in the SMALL model.

IBPSTACKEQU0; set to 1 if small reentrant is used.

IBPSTACKTOPEQU0FFH+1; set top of stack to highest location+1.

;

;Stack Space for reentrant functions in the LARGE model.

XBPSTACKEQU0; set to 1 if large reentrant is used.

XBPSTACKTOPEQU0FFFFH+1; set top of stack to highest location+1.

;

;Stack Space for reentrant functions in the COMPACT model.

PBPSTACKEQU0; set to 1 if compact reentrant is used.

PBPSTACKTOPEQU0FFFFH+1; set top of stack to highest location+1.

;----------------------------------------------------------------------

你必须设置你使用的存储模式的堆栈和设置栈顶。当有入栈时,再入函数的栈指针减少(向下移动)。为了保护内部的数据区,有一个技巧就是把所有的再入函数放在一个独立的存储模式,像large或compact。

用reentrant声明再入函数。

void reentrant_func (long arg1, long arg2, long arg3) reentrant

{

}

用large和reentrant声明一个large模式的再入函数。

void reentrant_func (long arg1, long arg2, long arg3) large reentrant

{

}

声明一个再入函数的函数指针,必须使用reentrant关键字。

void (*rfunc_ptr) (long, long, long) reentrant = reentrant_func;

再入函数的函数指针和非再入函数的函数指针没有许多不同。当使用再入函数指针时,会生成更多的代码,因为参数被压入模拟栈。然而,没有特殊的连接要求和不需要打乱“OVERLAY”指令。

如果通过间接调用传递超过3个参数给函数,需要再入函数指针。

使用再入指针的注意事项

keil中的函数递归调用可分为两种情况,一种是普通函数递归,调用时,新调用函数的程序储存空间覆盖原来的相同函数调用的程序储存空间,使得原来的局部变量消失了;还有一种是再入函数(用reentrant说明)的递归,每次递归,keil为再入函数生成一个模拟栈,再入函数参数和局部变量被放在这模拟栈中,这样使得原来调用函数的局部变量就没有消失了,而新的调用函数参数和局部变量又可以继续。


再入函数的定义:


函数类型 [reentrent] 函数名 (形式参数)


例如:int [reentrent]fution(char n)


{if(n<1)return(1);


else return(n*fution(n-1));


}


使用再入函数注意事项:


1: 再入函数不能传送bit类型的参数,函数内部也不能定义局部位变量,不能有位操作。总之与位有关的定义和操作在再入函数中都不能实现。


2:同一程序中可以有不同储存模式的再入函数,但是注意,任意模式的再入函数不能调用不同储存模式的再入函数,但可以调用不同储存模式的非再入函数。


3参数传递上,实际参数可以传递给间接调用的再入函数;非再入函数不能包含调用参数,因为那样会覆盖了原来的参数;但是,可以用全局变量来进行参数传递。


总结

函数指针是非常有用的,并不是很困难的,如果你注意连接调用树,保证用“OVERLAY”指令修正一些冲突。


上一页 1 2 3 下一页

评论


技术专区

关闭