7.调用约定_cdecl、_stdcall、_fastcall

1.什么是调用约定

调用约定跟堆栈清除密切相关。如果写一个汇编函数,给C/C++调用,在_cdecl方式下,则汇编函数无需清除堆栈,在_stdcall方式下,汇编函数需要在返回(RET)之前恢复堆栈

2.常用的调用约定

7.调用约定_cdecl、_stdcall、_fastcall_第1张图片

 3.VS编译器的调用约定

VS中默认的调用约定是_cdecl方式,Windows API使用_stdcall调用方式,在DLL导出函数中,为了跟Windows API保持一致,建议使用_stdcall方式

7.调用约定_cdecl、_stdcall、_fastcall_第2张图片

4.几种常用的调用约定

1)_cdecl约定

_cdecl调用约定又称为C调用约定,是C/C++语言缺省的调用约定。参数按照从右至左的方式入栈,函数本身不清理栈,此工作由调用者负责,返回值在EAX中。由于由调用者清理栈,所以允许可变参数函数的存在,如int sprintf(char * buffer, const char * format, ...)

2)_stdcall约定

_stdcall很多时候被称为pascal调用约定。pascal语言是早期很常见的一种教学用计算机程序设计语言,其语法严谨。参数按照从右至左的方式入栈,函数自身清理堆栈,返回值在EAX中

 3)_fastcall约定

顾名思义,_fastcall的特点就是快,因为它通过CPU寄存器来传递参数。它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数按照从右至左的方式入栈,函数自身清理堆栈,返回值在EAX中

4)_thiscall约定

这时C++语言特有的一种调用方式,用于类成员函数的调用约定。如果参数确定,this指针存放于ECX寄存器,函数自身清理堆栈;如果参数不确定,this指针在所有参数入栈后再入栈,调用者清理栈。_thiscall不是关键字,程序员不能使用。参数按照从右至左的方式入栈

 

5.不同调用约定下的函数名

7.调用约定_cdecl、_stdcall、_fastcall_第3张图片

 

6.调用约定导致的常见问题

如果定义的约定和使用的约定不一致,则将导致堆栈被破坏,导致下面常见的两种问题:

1)函数原型声明和函数体定义不一致

2)DLL导入函数时声明了不同的函数约定,例如在DLL导出时使用默认的_cdecl约定,然而在外部项目中使用DLL文件时,由于通过Win32 API利用WINAPI修饰时,就会导致堆栈被破坏

你可能感兴趣的:(静动态链接库)