看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《Smurf (哈里歐)》之銘言: : 我有兩個問題: : 1. 是因為_beginthreadex參數有__stdcall 所以callee要加call convention : 還是因為是呼叫OS的API所以才要加call convention呢? : 2. 我查資料後 文件是說__cdecl是C和C++程式的預設呼叫方式 : 那一般我們在宣告函式的時候 都不寫call convention是因為他預設是__cdecl呼叫 : 還是其他原因呢?? 1. 如果對方有需要stdcall, 那請用stdcall 2. 沒寫calling convention的話, 以編譯器設定為主, 編譯器可以指定"預設"的convention (如果也沒指定, 通常是cdecl) stdcall --> Pascal call, 由"被"呼叫的函數清除堆疊 cdecl --> 由呼叫別人的那部分程式碼來清除堆疊 fastcall --> C/C++自己搞的慣例, 可以使用EAX/EDX/ECX儲存參數(依序) (Delphi預設為fastcall) 不過如果大家都不寫組合語言的話, 只要大概知道速度上大約是fastcall > cdecl > stdcall (cdecl比stdcall快的原因是cdecl有助於整體的最佳化..., 通常是用add esp,xx就清完堆疊了) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.43.59.16
VictorTom:不好意思, 小弟對cdecl與stdcall有一點問題, 印象中看過 02/21 12:51
VictorTom:兩者的disasm code, 都可以用add esp,xx做完, 由於 02/21 12:52
VictorTom:stdcall是由callee做pop, 所以可以想見不需要程式裡每個 02/21 12:52
VictorTom:caller都寫一份pop, 因此stdcall的code size還比較小; 02/21 12:53
VictorTom:至於這點對效能的影響要再研究. 但是stdcall有一個問題 02/21 12:53
VictorTom:是, callee做pop無法應付C語言的不定長度參數, 所以遇到 02/21 12:54
VictorTom:這樣的func call時func必須要用cdecl. 印象中以前在 02/21 12:55
VictorTom:處理API interface時遇到問題測出來的結果是這樣, 有漏 02/21 12:55
VictorTom:誤的還請大大指正. PS. 使用的是VC++ 2005/2008. 02/21 12:56
cole945:能否支援不定長參數和 由誰清除堆疊 與 push參數順序 有關 02/21 16:47
cole945:由callee清除,那callee必定要知道參數長度. 而右往左push 02/21 16:48
cole945:參數,那第一個參數就會在stack的stop,有助於callee知道第 02/21 16:49
cole945:一個參數的位置(在不知道參數個數的情況下)所以cdecl較適 02/21 16:50
cole945:合處理不定長度參數.. 02/21 16:51
cole945:另外, pascal call和stdcall推參數的順序其實不同 @.@ 02/21 16:52
suhorng:V大跟c大已經說得很清楚了 另外推一下 stdcall 有時會使用 02/21 18:56
suhorng:ret XXX 的指令直接清除堆疊 02/21 18:56
補充說明一下, Pascal的部分確實可能是小弟弄錯了 (實際查了一下Pascal, 似乎順序相反) 至於cdecl適用於不定長度的參數, 這點也是確定的, 而整個程式的size較大這點也是確定的 對於embeded system, 或許也有可能是更糟糕的... 而我指出效能較好的部分主要是指目前的PC上, 效能大致是較好的 通常保留"越多東西"給主程式去進行最佳化(需要適當的編譯器),可以得到較好的整體效能 (其實最好的是全部都重新編譯, 並指定"全域"最佳化... XD) 這只是一般性的概念以及我之前自己測試的結果... 或許遇到一些特殊的情況, 也有可能跑得比較糟... (個人認為embeded system就極有可能比較糟) 以上也僅提供給各位參考 ※ 編輯: WPC001 來自: 123.195.63.235 (02/21 23:22)