DLL中呼叫約定和名稱修飾(二)

2021-04-15 01:49:09 字數 3162 閱讀 6803

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 編譯器往往按照...