C++反汇编->函数调用原理

    VC6.0++函数调用方式有三种:

    分别为:

1._stdcall 方式

int _stdcall add1(int i,int j)
{
	cout<<"_stdcall out"<<endl;
	return i+j;
}
0040158F      CC            INT3                                     ;  _stdcall 被调方平衡栈
00401590 > >  55            PUSH EBP
00401591   .  8BEC          MOV EBP,ESP
00401593   .  83EC 40       SUB ESP,40
00401596   .  53            PUSH EBX
00401597   .  56            PUSH ESI
00401598   .  57            PUSH EDI
00401599   .  8D7D C0       LEA EDI,DWORD PTR SS:[EBP-40]
0040159C   .  B9 10000000   MOV ECX,10
004015A1   .  B8 CCCCCCCC   MOV EAX,CCCCCCCC
004015A6   .  F3:AB         REP STOS DWORD PTR ES:[EDI]
004015A8   .  68 CD104000   PUSH testcall.004010CD
004015AD   .  68 1C004700   PUSH OFFSET testcall.??_C@_0N@HMEN@_stdc>;  _stdcall out
004015B2   .  68 A0DE4700   PUSH OFFSET testcall.std::cout
004015B7   .  E8 D8FCFFFF   CALL testcall.00401294
004015BC   .  83C4 08       ADD ESP,8
004015BF   .  8BC8          MOV ECX,EAX
004015C1   .  E8 24FCFFFF   CALL testcall.004011EA
004015C6   .  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
004015C9   .  0345 0C       ADD EAX,DWORD PTR SS:[EBP+C]
004015CC   .  5F            POP EDI
004015CD   .  5E            POP ESI
004015CE   .  5B            POP EBX
004015CF   .  83C4 40       ADD ESP,40
004015D2   .  3BEC          CMP EBP,ESP
004015D4   .  E8 D7F50100   CALL testcall.__chkesp
004015D9   .  8BE5          MOV ESP,EBP
004015DB   .  5D            POP EBP
004015DC   .  C2 0800       RETN 8
004015DF      CC            INT3
以上为DEBUG反汇编源码:


2._fastcall 方式

int _fastcall add2(int i, int j)
{
	cout<<"_fastcall out"<<endl;
	return i+j;
}
004015FF      CC            INT3                                     ;  _fastcall 被调方 平衡栈
00401600 > >  55            PUSH EBP
00401601   .  8BEC          MOV EBP,ESP
00401603   .  83EC 48       SUB ESP,48
00401606   .  53            PUSH EBX
00401607   .  56            PUSH ESI
00401608   .  57            PUSH EDI
00401609   .  51            PUSH ECX
0040160A   .  8D7D B8       LEA EDI,DWORD PTR SS:[EBP-48]
0040160D   .  B9 12000000   MOV ECX,12
00401612   .  B8 CCCCCCCC   MOV EAX,CCCCCCCC
00401617   .  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401619   .  59            POP ECX
0040161A   .  8955 F8       MOV DWORD PTR SS:[EBP-8],EDX
0040161D   .  894D FC       MOV DWORD PTR SS:[EBP-4],ECX
00401620   .  68 CD104000   PUSH testcall.004010CD
00401625   .  68 2C004700   PUSH OFFSET testcall.??_C@_0O@JLOO@_fast>;  _fastcall out
0040162A   .  68 A0DE4700   PUSH OFFSET testcall.std::cout
0040162F   .  E8 60FCFFFF   CALL testcall.00401294
00401634   .  83C4 08       ADD ESP,8
00401637   .  8BC8          MOV ECX,EAX
00401639   .  E8 ACFBFFFF   CALL testcall.004011EA
0040163E   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00401641   .  0345 F8       ADD EAX,DWORD PTR SS:[EBP-8]
00401644   .  5F            POP EDI
00401645   .  5E            POP ESI
00401646   .  5B            POP EBX
00401647   .  83C4 48       ADD ESP,48
0040164A   .  3BEC          CMP EBP,ESP
0040164C   .  E8 5FF50100   CALL testcall.__chkesp
00401651   .  8BE5          MOV ESP,EBP
00401653   .  5D            POP EBP
00401654   .  C3            RETN
以上为对应的DEBUG反汇编源码


3.cdecl 方式

int _cdecl add3(int i,int j)
{
	cout<<"_cdecl out"<<endl;
    return i+j;
}
00401670 > > \55            PUSH EBP                                 ;  保存栈底指针EBP
00401671   .  8BEC          MOV EBP,ESP                              ;  调整当前栈底指针位置到栈顶
00401673   .  83EC 40       SUB ESP,40                               ;  开辟栈空间  作为局部变量的存储空间
00401676   .  53            PUSH EBX                                 ;  保存EBX寄存器
00401677   .  56            PUSH ESI                                 ;  保存ESI寄存器
00401678   .  57            PUSH EDI                                 ;  保存EDI寄存器
00401679   .  8D7D C0       LEA EDI,DWORD PTR SS:[EBP-40]            ;  取出此函数 可用栈空间首地址
0040167C   .  B9 10000000   MOV ECX,10
00401681   .  B8 CCCCCCCC   MOV EAX,CCCCCCCC
00401686   .  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401688   .  68 CD104000   PUSH testcall.004010CD
0040168D   .  68 3C004700   PUSH OFFSET testcall.??_C@_0L@INPI@_cdec>;  _cdecl out
00401692   .  68 A0DE4700   PUSH OFFSET testcall.std::cout
00401697   .  E8 F8FBFFFF   CALL testcall.00401294
0040169C   .  83C4 08       ADD ESP,8
0040169F   .  8BC8          MOV ECX,EAX
004016A1   .  E8 44FBFFFF   CALL testcall.004011EA
004016A6   .  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]             ;  将EBP+8 处值 传送到EAX中
004016A9   .  0345 0C       ADD EAX,DWORD PTR SS:[EBP+C]             ;  将EBP+C 处值与EAX值 相加
004016AC   .  5F            POP EDI                                  ;  还原EDI 寄存器
004016AD   .  5E            POP ESI                                  ;  还原ESI寄存器
004016AE   .  5B            POP EBX                                  ;  还原EBX寄存器
004016AF   .  83C4 40       ADD ESP,40                               ;  降低栈顶,此时局部变量空间被释放
004016B2   .  3BEC          CMP EBP,ESP                              ;  检测栈平衡
004016B4   .  E8 F7F40100   CALL testcall.__chkesp                   ;  进入栈平衡错误检测函数
004016B9   .  8BE5          MOV ESP,EBP                              ;  还原ESP
004016BB   .  5D            POP EBP
004016BC   .  C3            RETN
以上为对应的DEBUG反汇编源码解释。


小结:

1.默认采用_cdecl方式。

2._fastcall方式 只是前两个参数用寄存器传递,后面的都采用栈传参方式。






C++反汇编->函数调用原理,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。