呼叫約定是指程式在函式呼叫時傳遞引數和獲取返回值所採用的方法:通過暫存器、或通過棧、或者是兩者的混合。用於指定calling convention的修飾符主要有:__cdecl,__stdcall,__fastcall等。呼叫約定可以通過工程設定:setting...\c/c++ \advanced\callingconvention 項進行選擇,預設狀態為__cdecl。它們決定以下內容:
1)、函式引數的壓棧順序,
2)、由呼叫者還是被呼叫者把引數彈出棧,
3)、以及產生函式修飾名的方法。
它們的各自特徵如下(以vs2005工具為例):
1.1、引數按從右到左的順序傳遞,放於棧中
1.2、棧的清空由主調函式完成
1.3、在生成的彙編**中,函式名以下劃線_ 開頭
編譯選項:/gd, 對於變參函式,如printf,只能用這種方式
2.1、函式的引數自右向左通過棧傳遞
2.2、被呼叫的函式在返回前清理傳送引數的記憶體棧
2.3、在生成的彙編**中,函式名以下劃線_ 開頭,以@和所有引數所占用的位元組數結尾。如call _sumexample@8
編譯選項:/gz,win32程式中的winapi即是__stdcall:#define winapi __stdcall,由於棧是由被調函式自己清空,其產生的執行**要小於__cdecl方式所產生的**。
3.1、前兩個引數要求不超過32bits,分別放入ecx和edx,其餘引數按從右到左的順序傳遞,放於棧中
3.2、引數由被調函式彈出棧
3.3、在生成的彙編**中,函式名以@開頭,以@和所有引數所占用的位元組數結尾
編譯選項:/gr
除這三種之外,還有thiscall,但它僅用於c++中類的成員函式:
1、引數按從右到左的順序傳遞,放於棧中。this放於ecx中
2、棧的清空有被調函式完成
這是c++中類成員函式預設的calling convention。但如果類的成員函式包含可變引數,那該函式的呼叫約定則是__cdecl。
c 和c++ 對應不同的呼叫約定,產生的修飾符也各不相同,對於函式test(void)如下:
呼叫約定
extern "c" 或 .c 檔案
.cpp、.cxx 或 /tp
__cdecl
_test
?test@@zaxxz
__fastcall
@test@0
?test@@yixxz
__stdcall
_test@0
?test@@ygxxz
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",例如
inttest1(char *var1,unsigned long)----"?test1@@yghpadk@z"
voidtest2()-----「?test2@@ygxxz」
__cdecl呼叫約定:
規則同上面的_stdcall呼叫約定,只是參數列的開始標識由上面的"@@yg"變為"@@ya"。
__fastcall呼叫約定:
規則同上面的_stdcall呼叫約定,只是參數列的開始標識由上面的"@@yg"變為"@@yi"。
vc++對函式的省缺宣告是"__cedcl",將只能被c/c++呼叫。
附:乙個dll在記憶體中只有乙個例項
dll程式和呼叫其輸出函式的程式的關係:
1)、dll與程序、執行緒之間的關係
dll模組被對映到呼叫它的程序的虛擬位址空間。
dll使用的記憶體從呼叫程序的虛擬位址空間分配,只能被該程序的執行緒所訪問。
dll的控制代碼可以被呼叫程序使用;呼叫程序的控制代碼可以被dll使用。
dlldll可以有自己的資料段,但沒有自己的堆疊,使用呼叫程序的棧,與呼叫它的應用程式相同的堆疊模式。
2)、關於共享資料段
dll定義的全域性變數可以被呼叫程序訪問;dll可以訪問呼叫程序的全域性資料。使用同一dll的每乙個程序都有自己的dll全域性變數例項。如果多個執行緒併發訪問同一變數,則需要使用同步機制;對乙個dll的變數,如果希望每個使用dll的執行緒都有自己的值,則應該使用執行緒區域性儲存(tls,thread localstrorage)
C 呼叫約定和名字約定
c 呼叫約定和名字約定 呼叫約定 cdecl fastcall與 stdcall,三者都是呼叫約定 calling convention 它決定以下內容 1 函式引數的壓棧順序,2 由呼叫者還是被呼叫者把引數彈出棧,3 以及產生函式修飾名的方法。1 stdcall呼叫約定 函式的引數自右向左通過棧傳...
C C 呼叫約定和名字約定
呼叫約定 cdecl stdcall 與 fastcall 三者都是呼叫約定 calling convention 它決定以下內容 1 函式引數的壓棧順序,2 由呼叫者還是被呼叫者把引數彈出棧,3 以及產生函式修飾名的方法。1 cdecl是c和c 程式的預設呼叫方式。每乙個呼叫它的函式都包含清空堆疊...
名字修飾約定和函式呼叫約定
所謂名字修飾約定,就是指變數名 函式名等經過編譯後重新輸出名稱的規則。比如源 中函式名稱為int func int a,int b 經過編譯後名稱可能為?func yahhh z func yghhh z func 8,也有可能與源 中名稱相同為func。影響編譯後輸出的名稱通常與名字修飾約定 ex...