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方式 只是前两个参数用寄存器传递,后面的都采用栈传参方式。