thiscall
thiscall
呼叫約定是
c++中的非靜態類成員函式的預設呼叫約定。
thiscall
只能被編譯器使用,沒有相應的關鍵字,因此不能被程式設計師指定。採用
thiscall
約定時,函式引數按照從右到左的順序入棧,被呼叫的函式在返回前清理傳送引數的棧,只是另外通過
ecx暫存器傳送乙個額外的引數:
this
指標。這次的例子中將定義乙個類,並在類中定義乙個成員函式,**如下:
class csum
};void main()
函式呼叫部分彙編**:
;csumsum;
;sum.add(1, 2);
push
2;引數從右到左入棧,先壓入
2push
1;壓入
1lea
ecx,[ebp-4];ecx
存放了this
指標call
@ilt+5(csum::add) (
0040100a
);呼叫函式實現
函式實現部分彙編**:
;int add(int a, int b)
push
ebpmov
ebp,esp
subesp,44h;
多用了乙個
4bytes
的空間用於存放
this
指標push
ebxpush
esipush
edipush
ecxlea
edi,[ebp-44h]
movecx,11h
moveax,0cccccccch
rep stos
dword ptr [edi]
popecx
movdword ptr [ebp-4],ecx
;return (a + b);
moveax,dword ptr [ebp+8]
addeax,dword ptr [ebp+0ch]
popedi
popesi
popebx
movesp,ebp
popebp
ret8;清棧
5
、
naked
屬性
採用上面所述的四種呼叫約定的函式在進入函式時,編譯器會產生**來儲存
esi、
edi、
ebx、
ebp暫存器中的值,退出函式時則產生**恢復這些暫存器的內容。對於定義了
naked
屬性的函式,編譯器不會自動產生這樣的**,需要你手工使用內嵌彙編來控制函式實現中的堆疊管理。由於
naked
屬性並不是型別修飾符,故必須和
__declspec
共同使用。下面的這段**定義了乙個使用了
naked
屬性的函式及其實現:
__declspec ( naked ) func()
_a**
}naked
屬性與本節關係不大,具體請參考
msdn
。6
、
winapi
還有乙個值得一提的是
winapi
巨集,它可以被翻譯成適當的呼叫約定以供函式使用。該巨集定義於
windef.h
之中。下面是在
windef.h
中的部分內容:
#define cdecl_cdecl
#define winapicdecl
#define callback__stdcall
#define winapi
__stdcall
#define apientry
winapi
由此可見,
winapi
、callback
、apientry
等巨集的作用。
2.名稱修飾(
name decoration)c
或c++
函式在內部(編譯和鏈結)通過修飾名(
decoration name
)識別。函式的修飾名是編譯器在編譯函式定義或者原型時生成的字串。編譯器在建立
.obj
檔案時對函式名稱進行修飾。有些情況下使用函式的修飾名是必要的,如在模組定義檔案裡頭指定輸出
c++過載函式、建構函式、析構函式,又如在彙編**裡呼叫c或
c++函式等。
在vc++
中,函式修飾名由編譯型別(c或
c++)、函式名、類名、呼叫約定、返回型別、引數等多種因素共同決定。下面分
c編譯、
c++編譯(非類成員函式)和
c++類及其成員函式編譯三種情況說明:
1
、
c編譯時函式名稱修飾
當函式使用
__cdecl
呼叫約定時,編譯器僅在原函式名前加上乙個下劃線字首,格式為
_functionname
。例如:函式
int __cdecl add(int a, int b)
,輸出後為:
_add。
當函式使用
__stdcall
呼叫約定時,編譯器在原函式名前加上乙個下劃線字首,後面加上乙個
@符號和函式引數的位元組數,格式為
_functionname@number
。例如:函式
int __stdcall add(int a, int b)
,輸出後為:
_add@8。
當函式是用
__fastcall
呼叫約定時,編譯器在原函式名前加上乙個
@符號,後面是加乙個
@符號和函式引數的位元組數,格式為
@functionname@number
。例如:函式
int __fastcall add(int a, int b)
,輸出後為:
@add@8。
以上改變均不會改變原函式名中的字元大小寫。
DLL 中呼叫約定和名稱修飾
呼叫約定 calling convention 是指在程式語言中為了實現函式呼叫而建立的一種協議。這種協議規定了該語言的函式中的引數傳送方式 引數是否可變和由誰來處理堆疊等問題。不同的語言定義了不同的呼叫約定。在c 中,為了允許操作符過載和函式過載,c 編譯器往往按照某種規則改寫每乙個入口點的符號名...
DLL中呼叫約定和名稱修飾
dll中呼叫約定和名稱修飾 一 呼叫約定 calling convention 是指在程式語言中為了實現函式呼叫而建立的一種協議。這種協議規定了該語言的函式中的引數傳送方式 引數是否可變和由誰來處理堆疊等問題。不同的語言定義了不同的呼叫約定。在c 中,為了允許操作符過載和函式過載,c 編譯器往往按照...
DLL中呼叫約定和名稱修飾(一)
dll中呼叫約定和名稱修飾 一 呼叫約定 calling convention 是指在程式語言中為了實現函式呼叫而建立的一種協議。這種協議規定了該語言的函式中的引數傳送方式 引數是否可變和由誰來處理堆疊等問題。不同的語言定義了不同的呼叫約定。在c 中,為了允許操作符過載和函式過載,c 編譯器往往按照...