一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

函數(shù)調(diào)用約定與函數(shù)名稱修飾規(guī)則(一)

 accesine 2005-08-11

      使用C/C++語(yǔ)言開發(fā)軟件的程序員經(jīng)常碰到這樣的問題:有時(shí)候是程序編譯沒有問題,但是鏈接的時(shí)候總是報(bào)告函數(shù)不存在(經(jīng)典的LNK 2001錯(cuò)誤),有時(shí)候是程序編譯和鏈接都沒有錯(cuò)誤,但是只要調(diào)用庫(kù)中的函數(shù)就會(huì)出現(xiàn)堆棧異常。這些現(xiàn)象通常是出現(xiàn)在C和C++的代碼混合使用的情況下或在C++程序中使用第三方的庫(kù)的情況下(不是用C++語(yǔ)言開發(fā)的),其實(shí)這都是函數(shù)調(diào)用約定(Calling Convention)和函數(shù)名修飾(Decorated Name)規(guī)則惹的禍。函數(shù)調(diào)用方式?jīng)Q定了函數(shù)參數(shù)入棧的順序,是由調(diào)用者函數(shù)還是被調(diào)用函數(shù)負(fù)責(zé)清除棧中的參數(shù)等問題,而函數(shù)名修飾規(guī)則決定了編譯器使用何種名字修飾方式來(lái)區(qū)分不同的函數(shù),如果函數(shù)之間的調(diào)用約定不匹配或者名字修飾不匹配就會(huì)產(chǎn)生以上的問題。本文分別對(duì)C和C++這兩種編程語(yǔ)言的函數(shù)調(diào)用約定和函數(shù)名修飾規(guī)則進(jìn)行詳細(xì)的解釋,比較了它們的異同之處,并舉例說(shuō)明了以上問題出現(xiàn)的原因。

函數(shù)調(diào)用約定(Calling Convention)

    函數(shù)調(diào)用約定不僅決定了發(fā)生函數(shù)調(diào)用時(shí)函數(shù)參數(shù)的入棧順序,還決定了是由調(diào)用者函數(shù)還是被調(diào)用函數(shù)負(fù)責(zé)清除棧中的參數(shù),還原堆棧。函數(shù)調(diào)用約定有很多方式,除了常見的__cdecl,__fastcall和__stdcall之外,C++的編譯器還支持thiscall方式,不少C/C++編譯器還支持naked call方式。這么多函數(shù)調(diào)用約定常常令許多程序員很迷惑,到底它們是怎么回事,都是在什么情況下使用呢?下面就分別介紹這幾種函數(shù)調(diào)用約定。


1.__cdecl

    編譯器的命令行參數(shù)是/Gd。__cdecl方式是C/C++編譯器默認(rèn)的函數(shù)調(diào)用約定,所有非C++成員函數(shù)和那些沒有用__stdcall或__fastcall聲明的函數(shù)都默認(rèn)是__cdecl方式,它使用C函數(shù)調(diào)用方式,函數(shù)參數(shù)按照從右向左的順序入棧,函數(shù)調(diào)用者負(fù)責(zé)清除棧中的參數(shù),由于每次函數(shù)調(diào)用都要由編譯器產(chǎn)生清除(還原)堆棧的代碼,所以使用__cdecl方式編譯的程序比使用__stdcall方式編譯的程序要大很多,但是__cdecl調(diào)用方式是由函數(shù)調(diào)用者負(fù)責(zé)清除棧中的函數(shù)參數(shù),所以這種方式支持可變參數(shù),比如printf和windows的API wsprintf就是__cdecl調(diào)用方式。對(duì)于C函數(shù),__cdecl方式的名字修飾約定是在函數(shù)名稱前添加一個(gè)下劃線;對(duì)于C++函數(shù),除非特別使用extern "C",C++函數(shù)使用不同的名字修飾方式。


2.__fastcall

    編譯器的命令行參數(shù)是/Gr。__fastcall函數(shù)調(diào)用約定在可能的情況下使用寄存器傳遞參數(shù),通常是前兩個(gè) DWORD類型的參數(shù)或較小的參數(shù)使用ECX和EDX寄存器傳遞,其余參數(shù)按照從右向左的順序入棧,被調(diào)用函數(shù)在返回之前負(fù)責(zé)清除棧中的參數(shù)。編譯器使用兩個(gè)@修飾函數(shù)名字,后跟十進(jìn)制數(shù)表示的函數(shù)參數(shù)列表大小,例如:@function_name@number。需要注意的是__fastcall函數(shù)調(diào)用約定在不同的編譯器上可能有不同的實(shí)現(xiàn),比如16位的編譯器和32位的編譯器,另外,在使用內(nèi)嵌匯編代碼時(shí),還要注意不能和編譯器使用的寄存器有沖突。


3.__stdcall
 
    編譯器的命令行參數(shù)是/Gz,__stdcall是Pascal程序的缺省調(diào)用方式,大多數(shù)Windows的API也是__stdcall調(diào)用約定。__stdcall函數(shù)調(diào)用約定將函數(shù)參數(shù)從右向左入棧,除非使用指針或引用類型的參數(shù),所有參數(shù)采用傳值方式傳遞,由被調(diào)用函數(shù)負(fù)責(zé)清除棧中的參數(shù)。對(duì)于C函數(shù),__stdcall的名稱修飾方式是在函數(shù)名字前添加下劃線,在函數(shù)名字后添加@和函數(shù)參數(shù)的大小,例如:_functionname@number

4.thiscall

    thiscall只用在C++成員函數(shù)的調(diào)用,函數(shù)參數(shù)按照從右向左的順序入棧,類實(shí)例的this指針通過ECX寄存器傳遞。需要注意的是thiscall不是C++的關(guān)鍵字,不能使用thiscall聲明函數(shù),它只能由編譯器使用。

5.naked call

    采用前面幾種函數(shù)調(diào)用約定的函數(shù),編譯器會(huì)在必要的時(shí)候自動(dòng)在函數(shù)開始添加保存ESI,EDI,EBX,EBP寄存器的代碼,在退出函數(shù)時(shí)恢復(fù)這些寄存器的內(nèi)容,使用naked call方式聲明的函數(shù)不會(huì)添加這樣的代碼,這也就是為什么稱其為naked的原因吧。naked  call不是類型修飾符,故必須和_declspec共同使用。

    VC的編譯環(huán)境默認(rèn)是使用__cdecl調(diào)用約定,也可以在編譯環(huán)境的Project Setting...菜單-》C/C++ =》Code  Generation項(xiàng)選擇設(shè)置函數(shù)調(diào)用約定。也可以直接在函數(shù)聲明前添加關(guān)鍵字__stdcall、__cdecl或__fastcall等單獨(dú)確定函數(shù)的調(diào)用方式。在Windows系統(tǒng)上開發(fā)軟件常用到WINAPI宏,它可以根據(jù)編譯設(shè)置翻譯成適當(dāng)?shù)暮瘮?shù)調(diào)用約定,在WIN32中,它被定義為__stdcall。   

(未完)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    狠狠亚洲丁香综合久久| 午夜亚洲少妇福利诱惑| 国产毛片不卡视频在线| 免费大片黄在线观看日本| 一个人的久久精彩视频| 熟女少妇一区二区三区蜜桃| 亚洲精品伦理熟女国产一区二区 | 91精品日本在线视频| 午夜资源在线观看免费高清| 国产一区欧美一区二区| 深夜日本福利在线观看| 91爽人人爽人人插人人爽| 精品欧美日韩一二三区| 午夜国产成人福利视频| 麻豆精品在线一区二区三区| 亚洲最新的黄色录像在线| 国产传媒免费观看视频| 国产激情国产精品久久源| 又黄又色又爽又免费的视频| 日韩综合国产欧美一区| 人妻中文一区二区三区| 91免费一区二区三区| 欧美日韩国产成人高潮| 黄色激情视频中文字幕| 好吊日视频这里都是精品| 日本亚洲精品在线观看| 国产精品午夜福利在线观看| 欧美一区二区三区性视频| 国产成人精品一区在线观看| 欧美日韩精品一区二区三区不卡| 国产欧美日产久久婷婷| 激情图日韩精品中文字幕| 插进她的身体里在线观看骚| 人人妻人人澡人人夜夜| 日韩欧美精品一区二区三区| 午夜国产福利在线播放| 精品国产av一区二区三区不卡蜜| 午夜精品久久久免费视频| 人妻少妇av中文字幕乱码高清| 中文字幕一区二区三区大片| 欧美日韩国产一级91|

    AI助手

    阅读时有疑惑?点击向AI助手提问吧

    联系客服

    微信扫码,添加客服企业微信

    客服QQ:

    1732698931

    联系电话:4000-999-276

    客服工作时间9:00-18:00,晚上非工作时间,请在微信或QQ留言,第二天客服上班后会立即联系您。