_stdcall,_cdecl與extern “C”

來源:互聯網
上載者:User

調用一個函數時,總是先把參數壓入棧,然後通過call指令轉移到被調用函數,在完成調用後清除堆棧.這裡有兩個問題:(1)哪個參數先入棧(2)由誰來清理堆棧.這兩個方面的問題稱為"呼叫慣例(Calling Conventions)"問題.

這裡只討論_stdcall和_cdecl呼叫慣例,前者是Windows API函數常用的呼叫慣例,後者即是C呼叫慣例.

_stcall:參數按從右向左的順序入棧,由被調用函數清理堆棧.
_cdecl :參數按從右向左的順序入棧,由調用函數清理堆棧.

為了防止函數名衝突,或者重載的需要(c++程式),編譯器通常都會修改使用者定義的函數名.

這樣說也許太抽象了,還是來看看具體的例子吧(通常代碼最能說明問題,也最能把問題說清楚).

來看一段簡單的代碼:

Code
void swap(int *x,int *y)
{
 int temp;
 temp=*x;
 *x=*y;
 *y=temp;
}


很簡單,即實現兩個數相交換,學過c語言的人對這段代碼應該很熟悉.
再來加一段測試代碼:

Code
int main(int argc, char* argv[])
{
    int a=4,b=5;
    swap(&a,&b);
    printf("a=%d,b=%d\n",a,b);
    return 0;
}


以下的測試基於VC++6.0.
(1)swap函數不加任何修飾(最簡單的情況)
來看看它們相應的彙編代碼:

//main調用swap的彙編代碼

swap(&a,&b);
00401096 8D 45 F8             lea         eax,[ebp-8]
00401099 50                   push        eax
0040109A 8D 4D FC             lea         ecx,[ebp-4]
0040109D 51                   push        ecx
0040109E E8 62 FF FF FF       call        @ILT+0(swap) (00401005)
004010A3 83 C4 08             add         esp,8

//swap的彙編代碼

void swap(int *x,int *y)
    {
00401020 55                   push        ebp
00401021 8B EC                mov         ebp,esp
00401023 83 EC 44             sub         esp,44h
00401026 53                   push        ebx
00401027 56                   push        esi
00401028 57                   push        edi
00401029 8D 7D BC             lea         edi,[ebp-44h]
0040102C B9 11 00 00 00       mov         ecx,11h
00401031 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401036 F3 AB                rep stos    dword ptr [edi]
        int temp;
        temp=*x;
00401038 8B 45 08             mov         eax,dword ptr [ebp+8]
0040103B 8B 08                mov         ecx,dword ptr [eax]
0040103D 89 4D FC             mov         dword ptr [ebp-4],ecx
       *x=*y;
00401040 8B 55 08             mov         edx,dword ptr [ebp+8]
00401043 8B 45 0C             mov         eax,dword ptr [ebp+0Ch]
00401046 8B 08                mov         ecx,dword ptr [eax]
00401048 89 0A                mov         dword ptr [edx],ecx
       *y=temp;
0040104A 8B 55 0C             mov         edx,dword ptr [ebp+0Ch]
0040104D 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401050 89 02                mov         dword ptr [edx],eax
   }
00401052 5F                   pop         edi
00401053 5E                   pop         esi
00401054 5B                   pop         ebx
00401055 8B E5                mov         esp,ebp
00401057 5D                   pop         ebp
00401058 C3                   ret

@ILT+0(?swap@@YAXPAH0@Z):
00401005 E9 16 00 00 00       jmp         swap (00401020)

swap被編譯器修改為 :?swap@@YAXPAH0@Z,這是c++轉換方式.

(2)_stdcall

 

swap(&a,&b);
004010E6 8D 45 F8             lea         eax,[ebp-8]
004010E9 50                   push        eax
004010EA 8D 4D FC             lea         ecx,[ebp-4]
004010ED 51                   push        ecx
004010EE E8 12 FF FF FF       call        @ILT+0(swap) (00401005)

void _stdcall swap(int *x,int *y)
    {
00401030 55                   push        ebp
00401031 8B EC                mov         ebp,esp
00401033 83 EC 44             sub         esp,44h
00401036 53                   push        ebx
00401037 56                   push        esi
00401038 57                   push        edi
00401039 8D 7D BC             lea         edi,[ebp-44h]
0040103C B9 11 00 00 00       mov         ecx,11h
00401041 B8 CC CC CC CC       mov         eax,0CCCCCCCCh
00401046 F3 AB                rep stos    dword ptr [edi]
        int temp;
        temp=*x;
00401048 8B 45 08             mov         eax,dword ptr [ebp+8]
0040104B 8B 08                mov         ecx,dword ptr [eax]
0040104D 89 4D FC             mov         dword ptr [ebp-4],ecx
       *x=*y;
00401050 8B 55 08             mov         edx,dword ptr [ebp+8]
00401053 8B 45 0C             mov         eax,dword ptr [ebp+0Ch]
00401056 8B 08                mov         ecx,dword ptr [eax]
00401058 89 0A                mov         dword ptr [edx],ecx
       *y=temp;
0040105A 8B 55 0C             mov         edx,dword ptr [ebp+0Ch]
0040105D 8B 45 FC             mov         eax,dword ptr [ebp-4]
00401060 89 02                mov         dword ptr [edx],eax
   }
00401062 5F                   pop         edi
00401063 5E                   pop         esi
00401064 5B                   pop         ebx
00401065 8B E5                mov         esp,ebp
00401067 5D                   pop         ebp
00401068 C2 08 00             ret         8

@ILT+0(?swap@@YGXPAH0@Z):
00401005 E9 16 00 00 00       jmp         swap (00401020)

(3)_cdecl

void _cdecl swap(int *x,int *y)

與第一種情況相同,即這是vc++預設的方式.

(4)extern "C" _cdecl 

void extern "C" _cdecl swap(int *x,int *y)

 

 swap(&a,&b);
00401096 8D 45 F8             lea         eax,[ebp-8]
00401099 50                   push        eax
0040109A 8D 4D FC             lea         ecx,[ebp-4]
0040109D 51                   push        ecx
0040109E E8 67 FF FF FF       call        @ILT+5(_swap) (0040100a)
004010A3 83 C4 08             add         esp,8

@ILT+5(_swap):
0040100A E9 11 00 00 00       jmp         swap (00401020)

swap被編譯器修改為_swap,即加一個底線(c語言轉換方式),其餘與第三種情況相同.

(5)extern "C" _stdcall

void extern "C" _stdcall swap(int *x,int *y)

 

swap(&a,&b);
00401096 8D 45 F8             lea         eax,[ebp-8]
00401099 50                   push        eax
0040109A 8D 4D FC             lea         ecx,[ebp-4]
0040109D 51                   push        ecx
0040109E E8 62 FF FF FF       call        @ILT+0(_swap@8) (00401005)

swap被修改為_swap@8,即加一個底線,後面加上參數在堆棧中所佔的位元組數(c語言轉換方式),其餘與第二種情況相同.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.