系統篇 小議三種函式呼叫約定

2022-01-12 08:01:20 字數 2176 閱讀 1653

小議三種函式呼叫約定

__cdecl

、__stdcall

、__fastcall

是c/c++

裡中經常見到的三種函式呼叫方式。其中__cdecl

是c/c++

預設的呼叫方式,__stdcall

是windows api

函式的呼叫方式,只不過我們在標頭檔案裡檢視這些api

的宣告的時候是用了winapi

的巨集進行代替了,而這個巨集其實就是__stdcall

了。三種呼叫方式的區別相信大家應該有些了解,這篇文章主要從例項和彙編的角度闡述這些區別的表現形態,使其對它們的區別認識從理論向實際過渡。

__cdecl:    c/c++

預設方式,引數從右向左入棧,主調函式負責棧平衡。

__stdcall:windows api

預設方式,引數從右向左入棧,被調函式負責棧平衡。

__fastcall:  

快速呼叫方式。所謂快速,這種方式選擇將引數優先從暫存器傳入(ecx

和edx

),剩下的引數再從右向左從棧傳入。因為棧是位於記憶體的區域,而暫存器位於cpu

內,故訪問方式快於記憶體,故其名曰「__fastcall

」。下面從例項來認識一下這三種呼叫約定。先來看乙個簡單的不能再簡單的程式了:

三個函式的內容都是一樣的,不同的是使用了三種呼叫的方式。我們先來看看在main

函式呼叫三個函式的時候的彙編**:

按照上面說的那樣,__cdecl

按照引數從右向左的方式進入棧區,注意fun1()

和fun3()

的區別,fun1()

在call fun1()

之後執行了add esp,8

。這一操作正是我們前面所說的進行棧的平衡。呼叫函式之前連續進行了兩次push

操作將函式所需的實參5

和2先後壓入了棧區,呼叫完成後,我們需要恢復呼叫前的狀態,則需調整棧頂指標esp

的位置,這一工作由誰來完成就決定了兩種函式呼叫方式__cdecl

(主調函式完成)和__stdcall

(被調函式完成)的產生。上圖我們看到了__cdecl

中由主調函式完成了,那麼__stdcall

呢,在被調函式fun3()

中,轉向被調函式結尾處的**,我們看到了這一句:

那麼fun1()

結尾處又是如何呢?

看到了吧,這個ret

指令後面跟沒跟值就決定了函式返回是棧指標esp

需要增加的量。這樣,不需要主調函式再呼叫add

指令為esp

操作平衡棧區,節約了程式的開銷,一條指令開銷小,如果十萬百萬個這樣的呼叫,這個開銷就明顯了。

說完了__cdecl

和__stdcall

,再來看看__fastcall

,如前面圖看到的呼叫時並未使用push

指令向棧裡傳引數,而是使用了

movedx, 5

movecx, 2

兩條指令。這樣直接將引數傳入暫存器,被調函式在執行的時候直接從暫存器取值即可,省去了從棧裡取出來給暫存器,再從暫存器取出來放入記憶體。

不過,說個題外話,ecx

暫存器經常作為計數和c++

裡this

指標的傳遞媒介。在這種情況下,情況又是怎樣的呢,下次分析c++

操作符new

的時候再予以討論。ecx

做計數器時,需要將ecx

中儲存的實參先壓入棧區,計數操作完成後再pop

出來。如此一來,這個fastcall

倒顯得不那麼fast

了。呵呵。

當然,上面所說的這些操作都是由編譯器在背後為我們完成的,開發人員無需關心這些操作,對我們是透明的。不過,知其然更知其所以然方能立於不敗之地!

三種函式呼叫約定

cdecl stdcall fastcall是c c 裡中經常見到的三種函式呼叫方式。其中 cdecl是c c 預設的呼叫方式,stdcall是windows api函式的呼叫方式,只不過我們在標頭檔案裡檢視這些api的宣告的時候是用了winapi的巨集進行代替了,而這個巨集其實就是 stdcall...

約定stdcall 函式呼叫的三種約定,你都清楚嗎

cdecl stdcall fastcall是c c 裡中經常見到的三種函式呼叫方式。其中 cdecl是c c 預設的呼叫方式,stdcall是windows api函式的呼叫方式,只不過我們在標頭檔案裡檢視這些api的宣告的時候是用了winapi的巨集進行代替了,而這個巨集其實就是 stdcall...

約定stdcall 函式呼叫的三種約定,你都清楚嗎

cdecl stdcall fastcall是c c 裡中經常見到的三種函式呼叫方式。其中 cdecl是c c 預設的呼叫方式,stdcall是windows api函式的呼叫方式,只不過我們在標頭檔案裡檢視這些api的宣告的時候是用了winapi的巨集進行代替了,而這個巨集其實就是 stdcall...