70,040
社区成员
发帖
与我相关
我的任务
分享

,和你说下我的心得吧
在gcc上测试
之前__cdecl指针能调用__stdcall函数应该只是个巧合,函数自身的栈空间足够大,调用__stdcall函数的次数少,所以没出岔子,调用次数一多就出问题了,因为esp一直是在加的
__stdcall指针调用__cdecl函数却是可行的,因为调用函数后不修改esp,esp就是在减的,相当于增加了main的栈空间。而且函数变量gcc通过ebp定位,而ebp在传参之后、调用函数之后入栈,最后可以准确还原,而传参通过esp定位,esp又是在减的,也就是传参的入栈位置都是在新的栈空间。
然后是cl的测试
__cdecl调用__stdcall一下就失败了,记得之前调用WinAPI是测试成功了的,忘了是什么情况了
不过它的__stdcall调用__cdecl也成功了,原因应该跟gcc的差不多,传参通过push,那么就是以esp定位,但不同的是,它变量是直接写的变量名,如move dword ptr[c] , 0 ,我估计本质应该也是用的ebp定位
话说调用约定会影响变参函数的参数的类型提升吗?
LoadLibrary+__cdecl函数指针调用Windows API,按理说会出问题的对吧,怪就怪在GCC和CL在命令行的编译结果运行正常,而VC的IDE上(CPP)就出问题了,得__stdcall函数指针。这波没出问题反而搞不懂,__cdecl和__stdcall都试了,汇编是不同的(调用后修改esp与否),但运行都正常???Windows API使用__stdcall的话,最后应该是修改了栈顶的吧?
还是这个__cdecl和__stdcall,在gcc上,__cdecl,调用函数后没有调整栈顶;__stdcall,调用后反而调整栈顶了,函数最后修改了栈顶,结果调用结束后gcc又改了回来,使栈顶还是指向调用各个函数时通用的传参空间。我是不是可以认为,表面上看是gcc对__cdecl没有修改栈顶而对__stdcall修改了,是由于它对栈的使用方式和VC不同,所以才造成了表象相反,在它的使用方式内,__cdecl没有改esp仍视为清理了栈,而__stdcall改了esp应视为没有清理栈,是吧?