Calling conventions(調用約定)
在聲明過程或函數時,你可以使用下面的指示字之一來指明調用約定:register、pascal、cdecl、stdcall以及safecall。比如,
function MyFunction(X, Y: Real): Real; cdecl;
...
調用約定決定了參數被傳遞給例程的順序,它們也影響從堆棧中刪除參數、傳遞參數時寄存器的使用,以及錯誤和異常處理。默認的調用約定是register。
• register 和pascal 調用從左到右傳遞參數,也就是說,最左邊的參數最早被計算並傳遞,最右邊的參數最後被計算和傳遞;cdecl、stdcall 和safecall 調用從右到左傳遞參數;
• 除了cdecl 調用,過程和函數在返回之前從堆棧中移除參數,而使用cdecl,當調用返回時,調用者從堆棧中移除參數;
• register 調用能使用多達3 個CPU 寄存器傳遞參數,而其它調用則全部使用堆棧傳遞參數;
• safecall 調用實現了異常“防火牆”,在Windows 下,它實現了進程間COM 錯誤通知。
下面的表格對調用約定進行了總結:
--------------------------------------------------------------------------------------------------
-指示字-------------- 參數順序--------- Clean-up ---------------使用寄存器傳遞參數?|
-register--------------- Left-to-right ---------Routine -----------------Yes---------------------||
-pascal --------------- Left-to-right ---------Routine -----------------No----------------------|
-cdecl----------------- Right-to-left ---------Caller --------------------No---------------------|
-stdcall ----------------Right-to-left ----------Routine --------------------No------------------|
-safecall--------------- Right-to-left ----------Routine --------------------No------------------|
-------------------------------------------------------------------------------------------------
默認的register 調用是最有效的,因為它通常避免了要創建堆棧結構(stack frame)(訪問公布屬性的方法必須使用register);當調用來自C/C++編寫的共享庫中的函數時,cdecl 是有用的;通常,當調用外部代碼時,推薦使用stdcall 和safecall。在Windows 中,系統API 使用stdcall 和safecall,其它操作系統通常使用cdecl(注意,stdcall 比cdecl 更有效)。
聲明雙重接口的方法必須使用safecall;保留pascal 調用是為了向後兼容性。要了解更多的調用約定的信息,請參考Program control。
指示字near、far 和export 用在16 位Windows 編程中,它們對32 位程序沒有影響,保留它們是為了向後兼容性。