• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天下

            記錄修行的印記

            函數調用、調用約定和名字約定

            函數調用、調用約定和名字約定

            調用約定:
            __cdecl __fastcall與 __stdcall,三者都是調用約定(Calling convention),它決定以下內容:
            1)函數參數的壓棧順序,
            2)由調用者還是被調用者把參數彈出棧
            3)以及產生函數修飾名的方法
                
            __cdecl
            __cdecl調用約定又稱為C調用約定,是 C
            /C++ 語言缺省的調用約定。參數按照從右至左的方式入棧,函數本身不清理棧,此工作由調用者負責,返回值在EAX中。
            對于 C,__cdecl 命名約定使用前面帶下劃線 (_) 的函數名;不執行任何大小寫轉換。對于C
            ++,除非聲明為 extern "C",否則 C++ 函數將使用不同的名稱修飾方案。    


            __stdcall 
            __stdcall調用約定參數按照從右至左的方式入棧,函數自身清理堆棧,返回值在EAX中。    
            對于 C,__stdcall 命名約定使用前面帶下劃線 (_) 的函數名,后跟“at”符 (@) 和函數的參數大?。ㄒ宰止潪閱挝唬?。不執行任何大小寫轉換。編譯器使用下列命名約定模板:
            _functionname@number

            __fastcall
            顧名思義,__fastcall 的特點就是快,因為它通過 CPU 寄存器來傳遞參數。他用 ECX 和 EDX 傳送前兩個雙字(DWORD)或更小的參數,剩下的參數按照從右至左的方式入棧,函數自身清理堆棧,返回值在 EAX 中。

            __thiscall
            這是 C
            ++ 語言特有的一種調用方式,用于類成員函數的調用約定。如果參數確定,this 指針存放于 ECX 寄存器,函數自身清理堆棧;如果參數不確定,this指針在所有參數入棧后再入棧,調用者清理棧。__thiscall 不是關鍵字,程序員不能使用。參數按照從右至左的方式入棧。

            名字修飾約定:
            1、修飾名(Decoration name):"C"或者"C++"函數在內部(編譯和鏈接)通過修飾名識別
            2、C編譯時函數名修飾約定規則:
            __stdcall調用約定在輸出函數名前加上一個下劃線前綴,后面加上一個
            "@"符號和其參數的字節數,格式為_functionname@number,例如:function(int a, int b),其修飾名為:_function@8
            __cdecl調用約定僅在輸出函數名前加上一個下劃線前綴,格式為_functionname。
            __fastcall調用約定在輸出函數名前加上一個
            "@"符號,后面也是一個"@"符號和其參數的字節數,格式為@functionname@number。

            3、C++編譯時函數名修飾約定規則:
            __stdcall調用約定:
            1)、以"?"標識函數名的開始,后跟函數名;
            2)、函數名后面以"@@YG"標識參數表的開始,后跟參數表;
            3)、參數表以代號表示:
            X
            --void ,
            D
            --char,
            E
            --unsigned char,
            F
            --short
            H
            --int,
            I
            --unsigned int
            J
            --long,
            K
            --unsigned long
            M
            --float,
            N
            --double
            _N
            --bool,
            PA
            --表示指針,后面的代號表明指針類型,如果相同類型的指針連續出現,以"0"代替,一個"0"代表一次重復;
            4)、參數表的第一項為該函數的返回值類型,其后依次為參數的數據類型,指針標識在其所指數據類型前;
            5)、參數表后以"@Z"標識整個名字的結束,如果該函數無參數,則以"Z"標識結束。
            其格式為
            "?functionname@@YG*****@Z""?functionname@@YG*XZ",例如
            int Test1(char *var1,unsigned long)----"?Test1@@YGHPADK@Z"
            void Test2()-----?Test2@@YGXXZ”

            __cdecl調用約定:
            規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的
            "@@YG"變為"@@YA"
            __fastcall調用約定:
            規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的
            "@@YG"變為"@@YI"
            VC
            ++對函數的省缺聲明是"__cedcl",將只能被C/C++調用.



            堆棧    
            棧:棧是向低地址擴展的數據結構,是一塊連續的內存的區域。
            棧又稱堆棧,是用戶存放程序臨時創建的局部變量,也就是函數括弧“{}”中定義的變量(但不包括static聲明的變量,)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,并且待到調用結束后,函數的返回值也會被存放回棧中。由于棧的先進后出特點,所以棧特別方便用來保存
            /恢復調用現場。從這個意義上,可以把堆??闯梢粋€寄存、交換臨時數據的內存區。  
              
            棧空間都是在運行時動態的分配的。
            函數堆棧在運行時動態分配,原因有二:
            一、無法在編譯時候確定函數運行時所需的堆棧大??;
            二、節省空間

            函數名就是一個指針,指向函數入口地址,也就是一個代碼段的地址。
            在內存中,數據和指令,堆棧分別在不同的地址段,數據段存儲的是程序的數據,代碼段存儲的是程序的指令,棧段是函數調用是保存參數和調用是上下文數據的內存區。棧由系統自動分配.

            函數名就指向一個代碼段的地址。對數據段的內存地址進行復引用操作(
            *a),得到內存中數據的值。如果對一個代碼段內存地址進行復引用操作,沒用什么實際意義,不可能返回一個指令。

            在標準c文檔(WG14 N1124)里這樣描述 
            A function designator 
            is an expression that has function type. Except when it is the
            operand of the 
            sizeof operator or the unary & operator, a function designator with
            type 
            "function returning type" is converted to an expression that has type "pointer to
            function returning type".

            也就是說函數類型表達式(如
            *pf)會被自動轉化成函數指針. 這樣你加多少個*都沒有關系. 

            另外對一個函數指針pf, (
            *pf)() 和 pf() 都已成為合法的用法 (k&R 不支持 pf())。

            C99 的文檔里也提到這一點:

            Pointers to functions may be used either 
            as (*pf)() or as pf(). The latter construct, not
            sanctioned 
            in K&R, appears in some present versions of C, is unambiguous, invalidates no old
            code, and can be an important shorthand. The shorthand 
            is useful for packages that present only
            one external name, which designates a structure full of pointers to objects and functions: member
            functions can be called 
            as graphics.open(file) instead of
            (
            *graphics.open)(file).

            說的是這樣子可以方便調用結構里的函數。
               

            posted on 2011-10-24 17:36 天下 閱讀(615) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

            <2012年6月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            導航

            統計

            常用鏈接

            留言簿(4)

            隨筆分類(378)

            隨筆檔案(329)

            鏈接

            最新隨筆

            搜索

            最新評論

            国产69精品久久久久777| 国内精品伊人久久久久| 久久久久久久波多野结衣高潮| 精品伊人久久久| 久久精品国产亚洲av麻豆小说| 精品久久人人妻人人做精品| 亚洲va中文字幕无码久久| 国产L精品国产亚洲区久久| 久久99久国产麻精品66| 91精品无码久久久久久五月天| 偷窥少妇久久久久久久久| 97超级碰碰碰碰久久久久| 久久亚洲精品无码AV红樱桃| 欧美精品一区二区久久| 成人综合伊人五月婷久久| 色播久久人人爽人人爽人人片AV| 欧美久久综合性欧美| 久久久久久亚洲AV无码专区| 久久亚洲中文字幕精品一区四| 亚洲欧美日韩精品久久| 99久久久精品免费观看国产| 久久妇女高潮几次MBA| 久久久久亚洲av成人网人人软件| 久久久久亚洲AV成人网人人软件| 日本精品久久久久中文字幕| 国产精品久久波多野结衣| 国产99精品久久| 国产精品青草久久久久婷婷| 久久精品国产亚洲AV麻豆网站 | 国产精品伦理久久久久久| 久久―日本道色综合久久| 狠狠狠色丁香婷婷综合久久俺| 粉嫩小泬无遮挡久久久久久| 久久99久久99小草精品免视看| 久久国产高潮流白浆免费观看| 欧美喷潮久久久XXXXx| 精品久久久久久无码专区| 99re久久精品国产首页2020| 秋霞久久国产精品电影院| 国产精品美女久久久久av爽| 欧美一级久久久久久久大|