資源描述:
《DLL中調(diào)用約定和名稱修飾》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、DLL中調(diào)用約定和名稱修飾調(diào)用約定(CallingConvention)是指在程序設(shè)計(jì)語言中為了實(shí)現(xiàn)函數(shù)調(diào)用而建立的一種協(xié)議。這種協(xié)議規(guī)定了該語言的函數(shù)中的參數(shù)傳送方式、參數(shù)是否可變和由誰來處理堆棧等問題。不同的語言定義了不同的調(diào)用約定。?在C++中,為了允許操作符重載和函數(shù)重載,C++編譯器往往按照某種規(guī)則改寫每一個(gè)入口點(diǎn)的符號(hào)名,以便允許同一個(gè)名字(具有不同的參數(shù)類型或者是不同的作用域)有多個(gè)用法,而不會(huì)打破現(xiàn)有的基于C的鏈接器。這項(xiàng)技術(shù)通常被稱為名稱改編(NameMangling)或者名稱修飾(NameDecoration)。許多C++編譯器廠商選擇了自己的名稱修飾方案。?因此,
2、為了使其它語言編寫的模塊(如VisualBasic應(yīng)用程序、Pascal或Fortran的應(yīng)用程序等)可以調(diào)用C/C++編寫的DLL的函數(shù),必須使用正確的調(diào)用約定來導(dǎo)出函數(shù),并且不要讓編譯器對(duì)要導(dǎo)出的函數(shù)進(jìn)行任何名稱修飾。一.調(diào)用約定(CallingConvention)調(diào)用約定用來處理決定函數(shù)參數(shù)傳送時(shí)入棧和出棧的順序(由調(diào)用者還是被調(diào)用者把參數(shù)彈出棧),以及編譯器用來識(shí)別函數(shù)名稱的名稱修飾約定等問題。在MicrosoftVC++6.0中定義了下面幾種調(diào)用約定,我們將結(jié)合匯編語言來一一分析它們:1、__cdecl__cdecl是C/C++和MFC程序默認(rèn)使用的調(diào)用約定,也可以在函數(shù)聲
3、明時(shí)加上__cdecl關(guān)鍵字來手工指定。采用__cdecl約定時(shí),函數(shù)參數(shù)按照從右到左的順序入棧,并且由調(diào)用函數(shù)者把參數(shù)彈出棧以清理堆棧。因此,實(shí)現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定。由于每一個(gè)使用__cdecl約定的函數(shù)都要包含清理堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會(huì)比較大。__cdecl可以寫成_cdecl。?下面將通過一個(gè)具體實(shí)例來分析__cdecl約定:?在VC++中新建一個(gè)Win32Console工程,命名為cdecl。其代碼如下:?int__cdeclAdd(inta,intb);????????//函數(shù)聲明?voidmain(){??????Add(1,2);??????
4、???????????????????????????//函數(shù)調(diào)用}?int__cdeclAdd(inta,intb)?????????//函數(shù)實(shí)現(xiàn){??????return(a+b);}?函數(shù)調(diào)用處反匯編代碼如下:?;Add(1,2);push????????????????????2??????????????????????????????????????;參數(shù)從右到左入棧,先壓入2push???????1???????????????????????????????????????;壓入1call????????@ILT+0(Add)(00401005)???;調(diào)用函數(shù)實(shí)現(xiàn)ad
5、d?????????esp,8??????????????????????????????????;由函數(shù)調(diào)用清棧2、__stdcall__stdcall調(diào)用約定用于調(diào)用Win32API函數(shù)。采用__stdcal約定時(shí),函數(shù)參數(shù)按照從右到左的順序入棧,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的棧,函數(shù)參數(shù)個(gè)數(shù)固定。由于函數(shù)體本身知道傳進(jìn)來的參數(shù)個(gè)數(shù),因此被調(diào)用的函數(shù)可以在返回前用一條retn指令直接清理傳遞參數(shù)的堆棧。__stdcall可以寫成_stdcall。?還是那個(gè)例子,將__cdecl約定換成__stdcall:?int__stdcallAdd(inta,intb){return(a+
6、b);}?函數(shù)調(diào)用處反匯編代碼:????????????;Add(1,2);push????????????????????2?????????????????????????????????????????????;參數(shù)從右到左入棧,先壓入2push???????1??????????????????????????????????????????????;壓入1call????????@ILT+10(Add)(0040100f)?????????;調(diào)用函數(shù)實(shí)現(xiàn)?函數(shù)實(shí)現(xiàn)部分的反匯編代碼:?;int__stdcallAdd(inta,intb)push????????????????
7、????ebpmov????????ebp,espsub??????????????esp,40hpush?????????????ebxpush?????????????esipush?????????????edilea?????????edi,[ebp-40h]mov????????ecx,10hmov???????eax,0CCCCCCCChrepstos?????dwordptr[edi];return(a+b);mov???????