反汇编分析__stdcall和__cdecl的异同

我下午写过__stdcall和__cdecl的异同了,都是从右向左将参数压入栈中,只不过我当时说__stdcall是自己清空栈,而__cdecl是主调代码环境清空栈,于是我刚才写了两个函数,用VC8.0编译器编译后反汇编得到汇编代码。

C++代码如下:
.h头文件
#pragma  once

#ifdef DLLTestAPI

#else
#define  DLLTestAPI _declspec(dllimport)
#endif

int  DLLTestAPI __stdcall add( int int );

int  DLLTestAPI __cdecl subtract( int int );

.cpp代码文件
#define  DLLTestAPI _declspec(dllexport)

#include 
" Test.h "

int  __stdcall add( int  a,  int  b)
{
    
return a + b;
}


int  __cdecl subtract( int  a,  int  b)
{
    
return a - b;
}

可以看到 add方法是使用__stdcall修饰的,而subtract方法是使用__cdecl修饰的。

反汇编后得到的汇编代码如下

add方法:
100115D0     55               PUSH EBP
100115D1    8BEC            MOV EBP,ESP
100115D3    81EC C0000000   SUB ESP,0C0
100115D9    
53               PUSH EBX
100115DA    
56               PUSH ESI
100115DB    
57               PUSH EDI
100115DC    8DBD 40FFFFFF   LEA EDI,DWORD PTR SS:[EBP
- C0]
100115E2    B9 
30000000      MOV ECX, 30
100115E7    B8 CCCCCCCC     MOV EAX,CCCCCCCC
100115EC    F3:AB           REP STOS DWORD PTR ES:[EDI]
100115EE    8B45 
08          MOV EAX,DWORD PTR SS:[EBP + 8 ]
100115F1    
0345  0C         ADD EAX,DWORD PTR SS:[EBP + C]
100115F4    5F              POP EDI
100115F5    5E              POP ESI
100115F6    5B              POP EBX
100115F7    8BE5            MOV ESP,EBP
100115F9    5D              POP EBP
100115FA    C2 
0800          RETN  8


subtract方法:
10011610      55               PUSH EBP
10011611     8BEC            MOV EBP,ESP
10011613     81EC C0000000   SUB ESP,0C0
10011619      53               PUSH EBX
1001161A    
56               PUSH ESI
1001161B    
57               PUSH EDI
1001161C    8DBD 40FFFFFF   LEA EDI,DWORD PTR SS:[EBP
- C0]
10011622     B9  30000000      MOV ECX, 30
10011627     B8 CCCCCCCC     MOV EAX,CCCCCCCC
1001162C    F3:AB           REP STOS DWORD PTR ES:[EDI]
1001162E    8B45 
08          MOV EAX,DWORD PTR SS:[EBP + 8 ]
10011631     2B45 0C         SUB EAX,DWORD PTR SS:[EBP + C]
10011634     5F              POP EDI
10011635     5E              POP ESI
10011636     5B              POP EBX
10011637     8BE5            MOV ESP,EBP
10011639     5D              POP EBP
1001163A    C3              RETN


大家已经看到了,他们的唯一区别是:
使用__stdcall修饰的add方法,最后的RETN指令的操作数是8,而使用__cdecl修饰的subtract方法,最后的RETN指令没有操作数。

RETN指令的操作数为什么是8呢,原因也很简单,就是add方法有两个int参数,也就是说压栈的时候压入了两个字节,正好8位,RETN 8的意思应该是让栈顶指针ESP向后移动8位。

你可能感兴趣的:(call)