函數(shù)調用約定是指對函數(shù)調用的約束和規(guī)范,主要包括三個方面
站在用戶的角度思考問題,與客戶深入溝通,找到貴定網站設計與貴定網站推廣的解決方案,憑借多年的經驗,讓設計與互聯(lián)網技術結合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:做網站、成都網站設計、企業(yè)官網、英文網站、手機端網站、網站推廣、空間域名、網絡空間、企業(yè)郵箱。業(yè)務覆蓋貴定地區(qū)。
- 函數(shù)參數(shù)壓棧的順序
- 參數(shù)出棧由調用者還是被調用者負責
- 函數(shù)名字修飾的方式
函數(shù)名修飾是編譯器在編譯階段創(chuàng)建的字符串用于標識函數(shù)的定義或原型,在鏈接程序或者一些工具中需要根據函數(shù)名字修飾來定位函數(shù)的具體位置
C++中為重載函數(shù)以及一些特殊函數(shù)(構造函數(shù)、析構函數(shù))指定名字修飾,在匯編程序中通過函數(shù)名修飾來調用C/C++函數(shù)
不同高級語言中使用的函數(shù)調用約定不同,這里以C/C++為例
C? ? ?:__cdecl、__stdcall、__fastcall、naked、__pascal
C++:__cdecl、__stdcall、__fastcall、naked、__pascal、__thiscall
__cdeclC/C++缺省的調用約定(c declaration),又被稱為Pascal調用
? 聲明語法:int __cdecl func(int, double)
- 參數(shù)壓棧順序:從右到左
- 參數(shù)出棧(恢復棧頂指針ESP):由調用者負責
- 函數(shù)名修飾方式:
?????C:在函數(shù)名前加上下劃線前綴,即_func
?????C++:函數(shù)名前加“?”前綴,函數(shù)名后加上@@YA和相關標識,即?func@@YAHHN@Z(具體的標識下文會列出
__stdcall標準調用約定(standard call),又被稱為Pascal調用,Windows?API使用此種調用方式
? 聲明語法:int __stdcall func(int, double)
- 參數(shù)壓棧順序:從右到左
- 參數(shù)出棧:由被調用者負責
- 函數(shù)名修飾方式:
?????C:在函數(shù)名前加上下劃線前綴,函數(shù)名后加上@和所有參數(shù)所占字節(jié)大小之和,即_func@12(本文以x64為例)
?????C++:函數(shù)名前加“?”,函數(shù)名后加上@@YG和相關參數(shù)標識,即?func@@YGHHN@Z
__fastcall快速調用約定(fast call),利用寄存器傳遞參數(shù),將前兩個DWORD或者更小的參數(shù)傳入到ECX和EDX中,其余參數(shù)按從右到左壓棧,參數(shù)的返回結果會傳入EAX
聲明語法:int __fastcall func(int, double)
- 參數(shù)壓棧順序:從右到左
- 參數(shù)出棧:由被調用者負責
- 函數(shù)名修飾方式:
?????C:在函數(shù)名前加上@前綴,函數(shù)名后加上@和所有參數(shù)所占字節(jié)大小之和,即@func@12
?????C++:函數(shù)名前加“?”,函數(shù)名后加上@@YI和相關參數(shù)標識,即?func@@YIHHN@Z
__thiscall??? ?? ? this指針調用約定,C++成員函數(shù)缺省的調用約定,不能顯式指明
- 參數(shù)壓棧順序:從右到左
?????若參數(shù)數(shù)量確定,則將this指針存入ECX再傳遞給被調用者,參數(shù)從右到左壓棧
?????若參數(shù)數(shù)量不確定,則先將參數(shù)從右到左壓棧,然后再將this指針壓棧
- 參數(shù)出棧:
?????若參數(shù)數(shù)量確定,則由被調用者負責
?????若參數(shù)數(shù)量不確定,則由調用者負責
- 函數(shù)名修飾方式(見下文)
naked裸函數(shù)調用,具體使用規(guī)則可以參考裸函數(shù)的規(guī)則和限制 | Microsoft Learn
聲明語法:__declspec(naked) int func(int, double)
__pascal聲明語法:int __pascal func(int, double)
- 參數(shù)壓棧順序:從右到左
- 參數(shù)出棧:由被調用者負責
該約定方式已經被棄用,一般用__stdcall來代替
__cdecl與__stdcall/__fastcall調用約定對比,大的不同在于參數(shù)出棧的控制方不同。__stdcall/__fastcall參數(shù)出棧由被調用方負責,即參數(shù)的出棧由被調用的函數(shù)負責,但是當函數(shù)為可變參函數(shù),函數(shù)無法正確處理參數(shù)出棧,此時應該由函數(shù)的調用方來控制參數(shù)出棧,因此可變參函數(shù)應該指明為__cdecl
C/C++函數(shù)名修飾規(guī)則__cdecl | __stdcall | __fastcall | |
C | "_" +?函數(shù)名 函數(shù)名加上“_”前綴,即_func | "_" +?函數(shù)名 + "@" + 參數(shù)字節(jié)大小 函數(shù)名加上“_”前綴,函數(shù)名后加上“@”和所有參數(shù)字節(jié)大小之和,即_func@21 | "@" +?函數(shù)名 +?"@" + 參數(shù)字節(jié)大小 函數(shù)名加上"@"前綴,函數(shù)名后加上“@”和所有參數(shù)字節(jié)大小之和,即@func@21 |
C++ | "?" +?函數(shù)名 + "@@YA" +?相關標識 函數(shù)名加上“?”前綴,函數(shù)名后加上“@@YA”和相關標識,即?func@@YAH_NHPEANPEBD@Z | "?" +?函數(shù)名 + "@@YG" +?相關標識 函數(shù)名加上“?”前綴,函數(shù)名后加上“@@YG”和相關標識,即?func@@YGH_NHPEANPEBD@Z | "?" +?函數(shù)名 + "@@YI" +?相關標識 函數(shù)名加上“?”前綴,函數(shù)名后加上“@@YI”和相關標識,即?func@@YI_NHPEANPEBD@Z |
注:上表以int func(bool, int, double*, const char*)為例
C++中三種函數(shù)名修飾主要區(qū)別在于后綴開始標識”@@YA”、“@@YG”、“@@YI”,其余標識修飾規(guī)則一致
上文提到的相關標識主要由三部分組成,相關標識 = 返回值標識+參數(shù)標識+結束標識,部分類型標識映射關系如下(基于VisualStudio 2022)
void | X |
char | D |
unsigned char | E |
short | F |
unsigned short | G |
int / __int32 | H |
unsigned int | I |
long | J |
unsigned long | K |
long long / __int64 | _J |
float | M |
double | N |
bool | _N |
struct | U |
* | PEA |
const* | PEB |
& | AEA |
const& | AEB |
struct | U |
class | V |
具體規(guī)則(以__cdecl為例):
struct和class作為參數(shù)時,由標識+結構/類名+"@@"組成,
對于結構體Data,Data?data對應的參數(shù)標識為UData@@;對于類CTest,CTest t對應的參數(shù)標識為VCTest@@
當有連續(xù)的相同類型的參數(shù)時,第二個開始的參數(shù)以“0”作為標識,但是在&,const&,*,const*時會有根據具體的順序將值遞增
void func(CTest t1, CTest t2, CTest t3, int a, CTest t4)? →???func@@YAXVTest@@00HVTest@@@Z
void func(CTest t1, CTest t2, CTest& t3, CTest& t4)? ? ? →???func@@YAXVTest@@00AEAV1@1@Z
若函數(shù)無參數(shù)則結束標識為“Z”,有參數(shù)則為“@Z”
void func()? ? ? →? ? ?func@@YAXXZ
void func(int)? →? ? ?func@@YAXH@Z
注:不同編譯器的修飾規(guī)則不一定相同,可以在cmd通過dumpbin從obj或lib中獲取程序中函數(shù)的修飾名,具體命令為dumpbin /symbols [filename]
__thiscall函數(shù)名修飾規(guī)則"?" +?函數(shù)名 + "@" +?類名 +?訪問權限標識 +?相關標識,其中相關標識規(guī)則如__cdel/__stdcall/__fastcall
訪問權限標識映射如下
public | @@QAE |
protected | @@IAE |
private | @@AAE |
示例:
class CTest
{
public:
????void setA(int a);
????int getA() const;
protected:
????void check();
private:
????void testInfo(const CTest& t);
};
setA? ? ? ?→? ??setA@CTest@@QAEXH@Z
check? ? ?→? ?check@CTest@@IAEXXZ
testInfo? ?→? ?testInfo@CTest@@AAEXAEBV1@@Z
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
新聞標題:C/C++函數(shù)調用規(guī)約-創(chuàng)新互聯(lián)
網站網址:http://aaarwkj.com/article48/dpjoep.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、虛擬主機、小程序開發(fā)、網站建設、定制網站、App設計
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)