1、要求
宣告定義處呼叫約定必須相同
int __stdcall add(int a, int b);
int __stdcall add(int a, int b)
return a + b;
2、函式呼叫過程
假設:a為呼叫者,b為被調者;a;
函式呼叫過程可以這麼描述:
(1)先將呼叫者(
a)的堆疊的基址(
ebp)入棧,以儲存之前任務的資訊。
(2)然後將呼叫者(
a)的棧頂指標(
esp)的值賦給
ebp,作為新的基址(即被呼叫者
b的棧底)。
(3)然後在這個基址(被呼叫者
b的棧底)上開闢(一般用
sub指令)相應的空間用作被呼叫者
b的棧空間。
(4)函式
b返回後,從當前棧幀的
ebp即恢復為呼叫者
a的棧頂(
esp),使棧頂恢復函式
b被呼叫前的位置;然後呼叫者
a再從恢復後的棧頂可彈出之前的
ebp值(可以這麼做是因為這個值在函式呼叫前一步被壓入堆疊)。這樣,
ebp和
esp就都恢復了呼叫函式
b前的位置,也就是棧恢復函式
b呼叫前的狀態。
這個過程在at&t彙編中通過兩條指令完成,即:
__cdecl 是
c declaration
的縮寫,表示
c 和
c++
預設的函式呼叫約定。是
c/c++
和mfcx
的預設呼叫約定。
按從右至左的順序壓引數入棧。a(b,c,d);先進d->c->b
由呼叫者把引數彈出棧。切記:對於傳送引數的記憶體棧是由呼叫者來維護的,返回值在eax中。因此對於像
printf
這樣可變引數的函式必須用這種約定。
編譯器在編譯的時候對這種呼叫規則的函式生成修飾名的時候,在輸出函式名前加上乙個下劃線字首,格式為_function。如函式
int add(int a, int b)
的修飾名是
_add
。4、__stdcall
__stdcall是
standard call
的縮寫,是
c++的標準呼叫方式
,當然這是微軟定義的標準,
__stdcall
通常用於
win32 api中(
可檢視winapi
的定義)
。按從右至左的順序壓引數入棧。
由被呼叫者把引數彈出棧。切記:函式自己在退出時清空堆疊,返回值在eax中。
__stdcall呼叫約定在輸出函式名前加上乙個下劃線字首,後面加上乙個「
@」符號和其引數的位元組數,格式為
_function@number
。如函式
int sub(int a, int b)
的修飾名是
_sub@8
。5、__fastcall
__fastcall呼叫的主要特點就是快,因為它是通過暫存器來傳送引數的。
實際上__fastcall用
ecx和
edx傳送前兩個
dword
或更小的引數,剩下的引數仍自右向左壓棧傳送,被呼叫的函式在返回前清理傳送引數的記憶體棧。
__fastcall呼叫約定在輸出函式名前加上乙個「
@」符號,後面也是乙個「
@」符號和其引數的位元組數,格式為
@function@number,
如double multi(double a, double b)
的修飾名是
@multi@16
。__fastcall和
__stdcall
很象,唯一差別就是頭兩個引數通過暫存器傳送。注意通過暫存器傳送的兩個引數是從左向右的,即第
1個引數進
ecx,第2個進
edx,其他引數是從右向左的入棧,返回仍然通過
eax。
6、__pascal
這種規則
從左向右傳遞引數,通過eax返回,堆疊由被呼叫者清除
7、__thiscall
__thiscall是
c++類成員函式預設的呼叫約定,但它沒有顯示的宣告形式。因為在
c++類中,成員函式呼叫還有乙個
this
指標引數,因此必須特殊處理,
thiscall
呼叫約定的特點:
引數入棧:引數從右向左入棧
his指標入棧:如果引數個數確定,
this
指標通過
ecx傳遞給被呼叫者;如果引數個數不確定,
this
指標在所有引數壓棧後被壓入棧。
棧恢復:對引數個數不定的,呼叫者清理棧,否則函式自己清理棧。
8、總結
呼叫規則
入棧順序
清棧責任
__cdecl
從右到左
呼叫者__stdcall
從右到左
被呼叫者
__fastcall
從右到左(先 edx、ecx,再到堆疊)
被呼叫者
__pascal
從左到右
被呼叫者
c 呼叫lua,lua呼叫c
建立工程 引用lua的動態庫和工程專案的配置資訊 結合 main.lua指令碼檔案 print lua呼叫c lua呼叫c 結合部分 c 向lua堆疊寫東西 通過lua堆疊 lua通過lua全域性標量獲取返回lua堆疊再到c lua傳遞數字給c cgivelua wangcheng 22,1 lua...
c 呼叫c和c呼叫c
c 的設計是相容c的,但是呼叫的時候還是需要遵循規則 1 包含標頭檔案 extern c 2 宣告呼叫的函式 extern c 為什麼要加extern c 1 c 語言支援函式過載,c語言不支援函式過載。2 函式被c 編譯後在庫中的名字與c語言的不同。void add int x,int y 該函式...
c 泛型約束
在定義泛型類時,可以對客戶端 能夠在例項化類時用於型別引數的型別種類施加限制。如果客戶端 嘗試使用某個約束所不允許的型別來例項化類,則會產生編譯時錯誤。這些限制稱為約束。約束是使用 where 上下文關鍵字指定的。下表列出了六種型別的約束 約束說明 t struct 型別引數必須是值型別。可以指定除...