所有的80x86 C编译器中都支持上面描述的标准C调用约定的规则。通常编译器也支持其它调用约定。当与汇编语言进行接口时,知道编译器调用你的函数时使用的是什么调用约定是非常重要的。通常,缺省时,使用的是标准的调用约定;但是,并不总是这一种情况。使用多种约定的编译器都拥有可以用来改变缺省约定的命令行开关。他们同样提供扩展的C语法来为单个函数指定调用约定。但是,各个编译器的这些扩展标准可以是不一样的。
GCC编译器允许不同的调用约定。一个函数的调用约定可以通过扩展语法__attribute__明确指定。例如,要声明一个返回值为空的函数f,它带有一个int参数,使用标准调用约定,需要使用下面的语法来声明它的圆形:
void f(int) __attribute__((cdecl));
GCC同样支持标准call调用约定。通过把cdecl替换成stdcall,上面的函数可以指定为使用这种约定。stdcall约定和cdecl约定的不同点是stdcall要求子程序将参数移除栈(和Pascal调用约定一样)。因此,stdcall调用约定只能使用在带有固定参数的函数上。
Borland和Microsoft使用一样语法来声明调用约定。他们在C代码中加上关键字_cdecl和_stdcall。这些关键字来修饰函数。在原型声明中,他们出现在函数名的前面:
void _cdecl f(int);
每种调用约定都有自己的优缺点。cdecl调用约定的主要有点是它非常简单而且灵活。它可以用于任何类型的C函数和C编译器。使用其它约定会限制子程序的可移植性。他的主要缺点是与其他约定相比它的执行较慢而且使用更多的内存。
stdcall调用约定的主要优点是相比于cdecl它使用较少的内存。在CALL指令之后,不需要清理堆栈。它的主要缺点是它不能用于可变参数的函数。
------------------------------------
Linux下
1.char get_cpu (void) __attribute__((cdecl));
2.char __attribute__((cdecl)) get_cpu (void) {...}
windows下
1.char _cdecl get_cpu (void);
2.char _cdecl get_cpu (void){...}
阅读(430) | 评论(0) | 转发(0) |