我发一个试试水。
函数调用方式: _cdecl:C\C++默认的调用方式,调用方平衡栈,不定参数的函数可以使用这种方式。 _stdcall:被调方平衡栈,不定参数的函数无法使用这种方式。 _fastcall:寄存器方式传参,被调方平衡栈,不定参数的函数无法使用这种方式。 这个平衡栈,意思就是说,在子函数运行完成后,是由调用的一方释放栈存储空间,还是被调用的函数在返回之前平衡栈空间。 x86应用程序的函数调用有上面三种方式,但是x64应用程序只有1中调用方式,名为寄存器快速调用约定。前四个参数使用寄存器传递,多余的参数就放到栈空间中,参数的传递顺序从右到左,由函数调用方平衡占空间。前四个参数存放的寄存器是固定的表格如下。还有,任意大于8字节或者不是1字节,2字节,4字节,8字节的参数是通过引用传递的。 参数 | | | 第1个参数 | | | 第2个参数 | | | 第3个参数 | | | 第4个参数 | | |
这里举个例子,如果是void func(float , float , int ,int) 那么前两个参数为XMM0,XMM1,后两个参数是R8,R9,而不是RCX,RDX。 这里值得注意的是,虽然前四个参数使用寄存器传递,但是相对应的栈空间(32位)仍然会预留。因为寄存器数量有限,一旦寄存器数量不够用,就可以把寄存器的值保存到预留的栈空间中。预留的空间也是由函数调用方平衡的。
在调用类成员函数的时候,还会遇到thiscall的默认调用约定,所有成员函数(非静态成员函数)都有一个隐藏参数,即自身类型的指针。调用成员函数过程中,默认利用ecx中保存的对象首地址,并以寄存器传参的方式将其传递到成员函数中。thiscall的栈平衡方式与__stdcall相同,都是被调用方负责平衡栈。在类中,如果定义的时候就选择其它调用方式,则this指针不再使用ecx传递,而是改用栈传递参数。 另外,平衡栈的操作有时会随着优化选项的不同而不同,有时是连续调用多个函数后,一次性平衡栈。部分调用方式也不是固定的,不同的编译器也会存在一定区别,具体情况还是根据反汇编调试时看到的为准。 |