看了一下gcc的汇编代码,与VC是相似的,没什么不同,没明白你说的意思
话说调用约定会影响变参函数的参数的类型提升吗? 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应视为没有清理栈,是吧?
Windows API大部分是__stdcall,只有变参函数是__cdecl,因为Windows API是已经编译好的,其调用约定已定
1、对于变参函数,其调用约定只能为__cdecl,因为只有调用者才知道传了多少个参数,被调用者是无法知道的(有标志意义的参数除外),所以这时也只能由调用者来做栈清理,恢复到调用前的状态 2、每次传参都是拿同一段空间反复使用,这本身就是栈的处理方式,是优于堆的地方,每一次函数调用后,都会恢复到调用前的状态,所以一般情况下栈不需要特别大的空间,函数式编程中的尾递归就是栈的极致利用方式 3、不论是那种调用约定,只要每一次函数调用后将栈恢复到调用前的状态,都可以认为是栈清理,也叫栈平衡
我主要有两个问题: 1. 关于变参函数,是不是不管声明何种调用约定,其都会实现为__cdecl?下面是VC的汇编,实际指定的是__stdcall。 2. gcc的对栈清理的方式怎么和VC不一样啊?或者说这算栈清理吗? 观察了它几次调用,发现它每次传参都是拿同一段空间反复使用,就是图中入栈的那段,对不同函数的调用,传参都是用的这同一段,作为调用方把控了传参的栈空间,是不是也相当于做了栈清理?或者说这能算栈清理吗? (编译用的32位,非x64约定)
69,371
社区成员
243,082
社区内容
加载中
试试用AI创作助手写篇文章吧