李緯的InsideVCL《第一章》中提到Windows定義的回調函數程序員
typedef LRESULT (CALLBACK*WNDPROC)(HWND,UNIT,WPARAM,LPARAM)ide
爲了加快回調函數執行的效率,Microsoft使用了CALLBACK修飾關鍵詞來定義WNDPROC,而CALLBACK則是定義成FAR PASCAL.函數
那麼爲何FARPASCAL就會更快執行呢?如下爲個人解釋測試
一般是C/C++所使用缺省的參數傳遞方式,它的傳遞方式是由右到左,並且當被調用的函數結束以後,將會由調用函數自己來清除堆棧上的參數數據。每個調用它的函數都包含清空堆棧的代碼,因此產生的可執行文件大小會比調用_stdcall函數的大。this
參數傳遞方式,也是由右到左,可是當被調用的函數結束以後,則是由被調用函數來清除堆棧上的參數數據,Win32API全部的輸出函數都是採用此中參數傳遞方式指針
是Delphi1.0與win16API所使用的參數傳遞方式,它的傳遞方式是由左到右,並且由被調用函數來清除堆棧上的參數數據.code
是Delphi默認所使用的參數傳遞方式, 主要特色就是快,由於它是經過寄存器來傳送參數的(實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧)orm
注:因此在引用C++動態庫中的函數時,要注意參數的傳遞方式,通常使用stdcall.還要注意字符串類型,C++在傳遞字符串時,都是採用字符指針的類型(Char *),因此你在Delphi的程序中就必須使用PCHAR類型,而不是string類型.內存
僅僅應用於「C++」成員函數。this指針存放於CX/ECX寄存器中,參數從右到左壓。thiscall不是關鍵詞,所以不能被程序員指定。字符串
當採用1-4的調用約定時,若是必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。(這些代碼稱做 prologand epilog code,通常,ebp,esp的保存是必須的).可是naked call不產生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。
其實。你只要寫一段下去測試。看它的 asm 就知道了。
TForm1.Test1Click(1,2, 3);
begin
0044E298 6A03 push$03
0044E29A 6A02 push$02
0044E29C 6A01 push$01
0044E29E 50 pusheax
0044E29F E8D4FFFFFF call TForm1.Test1
end
0044E2A4 C3 ret
0044E2A5 8D4000 lea eax,[eax+$00]
TForm1.Test2Click(1,2, 3);
begin
0044E287 6A03 push $03
0044E289 B902000000 mov ecx,$00000002
0044E28E BA01000000 mov edx,$00000001
0044E293 8BC3 mov eax,ebx
0044E295 E8CEFFFFFF call TForm1.Test2
end
0044E2B9 C3 ret
0044E2BA 8BC0 mov eax,eax
FunctionTForm1.Test1(a, b, c: Integer): Integer; stdcall;
Begin
0044E268 55 push ebp
0044E269 8BEC mov ebp,esp
Result := a + b + c;
0044E25B 8B450C mov eax,[ebp+$0c]
0044E25E 034510 add eax,[ebp+$10]
0044E261 034514 add eax,[ebp+$14]
end
0044E264 5D pop ebp
0044E265 C21000 ret $0010
FunctionTForm1.Test2(a, b, c: Integer): Integer; register;
Begin
0044E268 55 push ebp
0044E269 8BEC mov ebp,esp
Result := a + b + c;
0044E26B 8D0411 lea eax,[ecx+edx]
0044E26E 034508 add eax,[ebp+$08]
end
0044E271 5D pop ebp
0044E272 C20400 ret $0004
0044E275 8D4000 lea eax,[eax+$00]
這樣看起來。是否是就有所差別了?