• <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>

            天下

            記錄修行的印記

            函數(shù)調(diào)用、調(diào)用約定和名字約定

            函數(shù)調(diào)用、調(diào)用約定和名字約定

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


            __stdcall 
            __stdcall調(diào)用約定參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在EAX中。    
            對(duì)于 C,__stdcall 命名約定使用前面帶下劃線(xiàn) (_) 的函數(shù)名,后跟“at”符 (@) 和函數(shù)的參數(shù)大小(以字節(jié)為單位)。不執(zhí)行任何大小寫(xiě)轉(zhuǎn)換。編譯器使用下列命名約定模板:
            _functionname@number

            __fastcall
            顧名思義,__fastcall 的特點(diǎn)就是快,因?yàn)樗ㄟ^(guò) CPU 寄存器來(lái)傳遞參數(shù)。他用 ECX 和 EDX 傳送前兩個(gè)雙字(DWORD)或更小的參數(shù),剩下的參數(shù)按照從右至左的方式入棧,函數(shù)自身清理堆棧,返回值在 EAX 中。

            __thiscall
            這是 C
            ++ 語(yǔ)言特有的一種調(diào)用方式,用于類(lèi)成員函數(shù)的調(diào)用約定。如果參數(shù)確定,this 指針存放于 ECX 寄存器,函數(shù)自身清理堆棧;如果參數(shù)不確定,this指針在所有參數(shù)入棧后再入棧,調(diào)用者清理?xiàng)?。__thiscall 不是關(guān)鍵字,程序員不能使用。參數(shù)按照從右至左的方式入棧。

            名字修飾約定:
            1、修飾名(Decoration name):"C"或者"C++"函數(shù)在內(nèi)部(編譯和鏈接)通過(guò)修飾名識(shí)別
            2、C編譯時(shí)函數(shù)名修飾約定規(guī)則:
            __stdcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)下劃線(xiàn)前綴,后面加上一個(gè)
            "@"符號(hào)和其參數(shù)的字節(jié)數(shù),格式為_(kāi)functionname@number,例如:function(int a, int b),其修飾名為:_function@8
            __cdecl調(diào)用約定僅在輸出函數(shù)名前加上一個(gè)下劃線(xiàn)前綴,格式為_(kāi)functionname。
            __fastcall調(diào)用約定在輸出函數(shù)名前加上一個(gè)
            "@"符號(hào),后面也是一個(gè)"@"符號(hào)和其參數(shù)的字節(jié)數(shù),格式為@functionname@number。

            3、C++編譯時(shí)函數(shù)名修飾約定規(guī)則:
            __stdcall調(diào)用約定:
            1)、以"?"標(biāo)識(shí)函數(shù)名的開(kāi)始,后跟函數(shù)名;
            2)、函數(shù)名后面以"@@YG"標(biāo)識(shí)參數(shù)表的開(kāi)始,后跟參數(shù)表;
            3)、參數(shù)表以代號(hào)表示:
            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
            --表示指針,后面的代號(hào)表明指針類(lèi)型,如果相同類(lèi)型的指針連續(xù)出現(xiàn),以"0"代替,一個(gè)"0"代表一次重復(fù);
            4)、參數(shù)表的第一項(xiàng)為該函數(shù)的返回值類(lèi)型,其后依次為參數(shù)的數(shù)據(jù)類(lèi)型,指針標(biāo)識(shí)在其所指數(shù)據(jù)類(lèi)型前;
            5)、參數(shù)表后以"@Z"標(biāo)識(shí)整個(gè)名字的結(jié)束,如果該函數(shù)無(wú)參數(shù),則以"Z"標(biāo)識(shí)結(jié)束。
            其格式為
            "?functionname@@YG*****@Z""?functionname@@YG*XZ",例如
            int Test1(char *var1,unsigned long)----"?Test1@@YGHPADK@Z"
            void Test2()-----?Test2@@YGXXZ”

            __cdecl調(diào)用約定:
            規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開(kāi)始標(biāo)識(shí)由上面的
            "@@YG"變?yōu)?/span>"@@YA"。
            __fastcall調(diào)用約定:
            規(guī)則同上面的_stdcall調(diào)用約定,只是參數(shù)表的開(kāi)始標(biāo)識(shí)由上面的
            "@@YG"變?yōu)?/span>"@@YI"。
            VC
            ++對(duì)函數(shù)的省缺聲明是"__cedcl",將只能被C/C++調(diào)用.



            堆棧    
            棧:棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。
            棧又稱(chēng)堆棧,是用戶(hù)存放程序臨時(shí)創(chuàng)建的局部變量,也就是函數(shù)括弧“{}”中定義的變量(但不包括static聲明的變量,)。除此以外,在函數(shù)被調(diào)用時(shí),其參數(shù)也會(huì)被壓入發(fā)起調(diào)用的進(jìn)程棧中,并且待到調(diào)用結(jié)束后,函數(shù)的返回值也會(huì)被存放回棧中。由于棧的先進(jìn)后出特點(diǎn),所以棧特別方便用來(lái)保存
            /恢復(fù)調(diào)用現(xiàn)場(chǎng)。從這個(gè)意義上,可以把堆棧看成一個(gè)寄存、交換臨時(shí)數(shù)據(jù)的內(nèi)存區(qū)。  
              
            ??臻g都是在運(yùn)行時(shí)動(dòng)態(tài)的分配的。
            函數(shù)堆棧在運(yùn)行時(shí)動(dòng)態(tài)分配,原因有二:
            一、無(wú)法在編譯時(shí)候確定函數(shù)運(yùn)行時(shí)所需的堆棧大小;
            二、節(jié)省空間

            函數(shù)名就是一個(gè)指針,指向函數(shù)入口地址,也就是一個(gè)代碼段的地址。
            在內(nèi)存中,數(shù)據(jù)和指令,堆棧分別在不同的地址段,數(shù)據(jù)段存儲(chǔ)的是程序的數(shù)據(jù),代碼段存儲(chǔ)的是程序的指令,棧段是函數(shù)調(diào)用是保存參數(shù)和調(diào)用是上下文數(shù)據(jù)的內(nèi)存區(qū)。棧由系統(tǒng)自動(dòng)分配.

            函數(shù)名就指向一個(gè)代碼段的地址。對(duì)數(shù)據(jù)段的內(nèi)存地址進(jìn)行復(fù)引用操作(
            *a),得到內(nèi)存中數(shù)據(jù)的值。如果對(duì)一個(gè)代碼段內(nèi)存地址進(jìn)行復(fù)引用操作,沒(méi)用什么實(shí)際意義,不可能返回一個(gè)指令。

            在標(biāo)準(zhǔn)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".

            也就是說(shuō)函數(shù)類(lèi)型表達(dá)式(如
            *pf)會(huì)被自動(dòng)轉(zhuǎn)化成函數(shù)指針. 這樣你加多少個(gè)*都沒(méi)有關(guān)系. 

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

            C99 的文檔里也提到這一點(diǎn):

            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).

            說(shuō)的是這樣子可以方便調(diào)用結(jié)構(gòu)里的函數(shù)。
               

            posted on 2011-10-24 17:36 天下 閱讀(600) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): C/C++

            <2015年12月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(4)

            隨筆分類(lèi)(378)

            隨筆檔案(329)

            鏈接

            最新隨筆

            搜索

            最新評(píng)論

            一本久道久久综合狠狠躁AV | AV狠狠色丁香婷婷综合久久 | 久久亚洲私人国产精品vA| 久久久无码精品亚洲日韩蜜臀浪潮 | 久久99国内精品自在现线| 色综合久久最新中文字幕| 欧美伊人久久大香线蕉综合69| 久久免费的精品国产V∧| 久久精品一区二区影院| 精品久久久久久久久午夜福利| 理论片午午伦夜理片久久| 精品熟女少妇a∨免费久久| 久久男人AV资源网站| 久久91综合国产91久久精品| 亚洲人成电影网站久久| 国产精品免费久久| 国产精品久久久久久| 久久成人国产精品免费软件| 理论片午午伦夜理片久久 | 伊人热热久久原色播放www| 久久精品人人做人人妻人人玩| 日韩电影久久久被窝网| 国产精品gz久久久| 情人伊人久久综合亚洲| 久久99精品国产麻豆| 亚洲成色WWW久久网站| 亚洲国产日韩欧美久久| 久久久久亚洲av毛片大| 91亚洲国产成人久久精品网址| 久久精品国产亚洲AV无码偷窥| 99久久精品国产一区二区| 亚洲国产成人久久综合碰| 久久男人AV资源网站| 久久久久久噜噜精品免费直播| 国产精品久久久久久久久久免费| 久久91精品国产91久久小草| 久久国产高潮流白浆免费观看| 精品蜜臀久久久久99网站| 久久久久亚洲av无码专区| 国产精品99久久99久久久| 成人免费网站久久久|