Anonymous 发表于 2016-12-12 18:56:42

各种调用方式的笔记

本帖最后由 匿名 于 2016-12-12 20:33 编辑

参考C++反汇编与逆向分析技术揭秘,这本书讲的非常好,推荐大家去看看

VC++环境下的调用约定有三种,_cdecl,_stdcall,_fastcall.这三种调用约定解释如下:

_cdecl:C/C++默认调用方式,调用方平衡栈,不定参数的函数可以使用。

_stdcall:被调用方平衡栈,不定参数的函数无法使用。

_fastcall:寄存器方式传参,被调用方平衡栈,不定参数函数无法使用。

所谓的调用方与被调用方理解:

例如:
                push 1
                push 2
                push 3
                call xxxxx
                add esp,0xC
调用方负责平衡栈意思是当函数结束的时候,也就是call后面直接add esp,push个数*4


被调用方负责平衡栈意思是当函数结束的时候,进行ret 操作,也就是会有ret 4、ret 8之类的。

_cdecl调用方式在函数内没有任何平衡参数操作,而在退出函数后对esp执行加8操作

Show_cdecl(10, 11);
00BF1547push      0Bh
00BF1549push      0Ah
00BF154Bcall      Show_cdecl (0BF11D6h)
00BF1550add         esp,8//这里平衡参数
_stdcall调用方式在函数内进行retpush参数*4进行堆栈平衡,与_cdecl调用方式相反

Show_stdcall(7, 8);
00BF153Epush      8
00BF1540push      7
00BF1542call      Show_stdcall (0BF106Eh)

00BF14EDpop         edi   
00BF14EEpop         esi
00BF14EFpop         ebx
00BF14F0add         esp,0C0h
00BF14F6cmp         ebp,esp
00BF14F8call      __RTC_CheckEsp (0BF1145h)
00BF14FDmov         esp,ebp
00BF14FFpop         ebp
00BF1500ret         8         //这里进行平衡参数
_fastcall:寄存器方式传参,被调用方平衡栈,不定参数函数无法使用

好处是:传递效率高,因为是使用寄存器所以函数结束不用清空栈
坏处是:就只能用两个寄存器ecx,edx大于2就只能乖乖的用栈传递参数
Show_fastcall(22, 33);
00BF1553mov         edx,21h
00BF1558mov         ecx,16h
00BF155Dcall      Show_fastcall (0BF1154h)
        return 0;
00BF1562xor         eax,eax

例如这个例子:
_fastcall而寄存器比较少,它只使用了ecx,edx保存第一个和第二个参数,其余的放在堆栈操作
Show_fastcall(22, 33,44);
012D1553push      2Ch       //大于2个参数只能用栈
012D1555mov         edx,21h
012D155Amov         ecx,16h
012D155Fcall      Show_fastcall (012D11EAh)

012D1499mov         esp,ebp
012D149Bpop         ebp
012D149Cret         4
页: [1]
查看完整版本: 各种调用方式的笔记