函数调用与约定
2014-08-20 15:19
232 查看
此前看教程,函数调用与约定。。看完之后不明不白的。。这个东西到底有什么用。。现在 也是不太明白。。只是觉得 这个就像是使用了一些系统预先设置 的规则 卡一样。。
可能理解的有些不准确。。欢迎指出。。今天又在看那个教程。。百度搜了下。。看到以为CSDN的大牛~有文章介绍了这个知识点。。于是就毫不留情的搬了过来。。刚好自己的博客也刚建。。。收藏知识库了~多谢作者~
函数调用约定决定以下内容:
1)函数参数的压栈顺序
2)由调用者还是被调用者把参数弹出栈
3)以及产生函数修饰名的方法
一般WIN32的函数都是__stdcall
#define CALLBACK __stdcall
#define WINAPI __stdcall
WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结 构)。
当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除?如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来 讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。如果使用 __stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以 WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知 道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好 使用__stdcall关键字。
原文作者介绍的很详细,原文末尾可以看到作者参考了大量专业书籍。。这种精神~致敬~
原文地址在文章末尾处。
我稍微记录下。。如果有不对的,请指出。谢谢
1. __cdecl
常用,为系统缺省的调用方式 参数的压入顺序为从右往左,栈上的参数由调用者清除
2. __stdcall
调用广泛 ,大多数WIN API都是这种调用方式,参数的压入顺序为从右往左,栈上的参数由函数清除
3. __fastcall
使用较少,参数的压入顺序为从右往左,把第一第二个参数放入寄存器(ECX ,EDX)中。。栈上的参数由函数清除
【__fastcall也有__stdcall的缺点:不支持可变参数个数的函数。】
4. 一些过时的调用约定 __pascal, __fortran 和__syscall是三种已经过时的调用约定,MSDN的建议是使用WINAPI宏,也就是__stdcall来代替原来的PASCAL和 __far __pascal。
5. thiscall
在VS2005之前,仅应用于C++的成员函数:
把this指针存放于CX寄存器,参数从右到左压栈,由函数来负责清除参数。 【不支持可变参数】
6. __clrcall
只能被托管代码(managed code)调用
7. Naked 函数调用
这是VC 里一种给高级用户使用的调用约定,它实际上就是没有规范,用户可以通过内嵌汇编来实现任意想要得调用约定。由于我们平时编程时基本上不会去使用它,
参考自http://blog.csdn.net/zjwoody/article/details/7887988
稍有增删
可能理解的有些不准确。。欢迎指出。。今天又在看那个教程。。百度搜了下。。看到以为CSDN的大牛~有文章介绍了这个知识点。。于是就毫不留情的搬了过来。。刚好自己的博客也刚建。。。收藏知识库了~多谢作者~
函数调用约定决定以下内容:
1)函数参数的压栈顺序
2)由调用者还是被调用者把参数弹出栈
3)以及产生函数修饰名的方法
一般WIN32的函数都是__stdcall
#define CALLBACK __stdcall
#define WINAPI __stdcall
WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结 构)。
当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除?如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来 讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。如果使用 __stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以 WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知 道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好 使用__stdcall关键字。
原文作者介绍的很详细,原文末尾可以看到作者参考了大量专业书籍。。这种精神~致敬~
原文地址在文章末尾处。
我稍微记录下。。如果有不对的,请指出。谢谢
1. __cdecl
常用,为系统缺省的调用方式 参数的压入顺序为从右往左,栈上的参数由调用者清除
2. __stdcall
调用广泛 ,大多数WIN API都是这种调用方式,参数的压入顺序为从右往左,栈上的参数由函数清除
3. __fastcall
使用较少,参数的压入顺序为从右往左,把第一第二个参数放入寄存器(ECX ,EDX)中。。栈上的参数由函数清除
【__fastcall也有__stdcall的缺点:不支持可变参数个数的函数。】
4. 一些过时的调用约定 __pascal, __fortran 和__syscall是三种已经过时的调用约定,MSDN的建议是使用WINAPI宏,也就是__stdcall来代替原来的PASCAL和 __far __pascal。
5. thiscall
在VS2005之前,仅应用于C++的成员函数:
把this指针存放于CX寄存器,参数从右到左压栈,由函数来负责清除参数。 【不支持可变参数】
6. __clrcall
只能被托管代码(managed code)调用
7. Naked 函数调用
这是VC 里一种给高级用户使用的调用约定,它实际上就是没有规范,用户可以通过内嵌汇编来实现任意想要得调用约定。由于我们平时编程时基本上不会去使用它,
参考自http://blog.csdn.net/zjwoody/article/details/7887988
稍有增删
相关文章推荐
- 函数调用约定解析 转载自:http://www.allaboutprogram.com
- 函数调用约定解析
- 函数调用约定
- 函数调用约定解析 汇编解析
- 函数的调用约定
- 函数调用约定
- 函数调用约定和堆栈
- [转载]论函数调用约定
- 函数调用约定:_stdcall,_cdecl,_fastcall
- 函数调用约定 stdcall, cdecl
- 函数调用约定
- dll的输出函数使用__stdcall调用约定后,客户端用GetProcAddress出现的问题!
- Delphi中调用C约定不定参数函数的调用方法.
- 动态库输出函数的约定:调用约定和名字修饰约定。
- 函数命名规则及调用约定(__cdecl,__stdcall,__fastcall)
- 转贴:论函数调用约定
- 对几种函数调用约定的总结
- 函数调用约定
- 函数调用约定收藏
- 函数调用约定