前言
Delphi做爲一個快速高效的開發平臺,使用的人愈來愈多,但熟悉在Delphi代碼中嵌入ASM代碼的程序員我想很少,由於這方面的資料太少了,另外一方面,它還須要有基本的彙編語言知識,關於彙編語言的教程,那實在太多了,若是你對彙編語言不熟的話,建議你下載相交的教程先讀讀。所以,本文假定您已經熟悉了彙編語言。
(注,下文中的函數與過程統稱爲函數。)
一.如何在Delphi程序中增長一段彙編代碼?
很簡單,用asm...end把你的彙編代碼封裝起來,再把它放到你須要它的位置.這個須要它的位置能夠是函數的begin與end之間,也能夠是Program的begin與end之間,固然,好能夠是initialization與end之間或finalization與end之間,一句話,任何能夠放Delphi執行代碼的地方。
範例1:對變量X實現邏輯循環右移8位,它告訴您如何在過程程中插入一段asm代碼。程序員
procedure TForm1.Button1Click(Sender: TObject); var X:DWORD; begin X:=$FF000000; ShowMessage(Format('移位前: %.8X',[X])); asm MOV EAX, X ROR EAX, 8 MOV X, EAX end; ShowMessage(Format('移位後: %.8X',[X])); end;
怎麼樣,是否是很簡單?函數
二.如何在彙編代碼中調用函數?
首先,須要講一下函數的調用方式。
在Delphi中,函數的調用方式有五種,分別是register,pascal,cdecl,stdcall以及safecall,最經常使用的是register及stdcall方式.如何區別這五種方式,它們之間依據三個方面來區分,第一是參數傳遞順序(Parameter Order),第二是堆棧清除方(Clean-up),第三是是否以寄存器來傳遞參數(Passes parameters in registers?).您能夠在Delphi Help中找到相關資料。
Delphi中默認的參數傳遞方式是register,即不加方式聲明的狀況下,都是register方式.register方式的參數傳遞順序是從左到右,由被調用者來清除堆棧,而且使用寄存器來傳遞參數。如何使用寄存器來傳遞參數呢?第一個參數使用EAX,第二個參數使用EDX,第三個參數使用ECX,第四個及之後的參數使用堆棧來傳遞,而且這些使用堆棧的參數是從左到右入棧的。
stdcall是Windows的默認參數傳遞方式,它不使用寄存器來傳遞參數,這種方式下參數的傳遞順序是從右到左,即最後一個參數第一個入棧,依次向前,按倒序入棧。spa
範例2:用asm代碼調用MessageBox函數,它告訴您如何在asm中調用stdcall方式的函數。code
procedure TForm1.Button2Click(Sender: TObject); var szTitle:string; szCaption:string; begin szTitle:='您好!'; szCaption:='這是一個在內嵌彙編中調用stdcall類型函數的例子.'; asm PUSH MB_OK+MB_ICONINFORMATION PUSH szTitle PUSH szCaption PUSH 0 CALL MessageBox end; end;
先來看看MessageBox函數的聲明:
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
這個函數的調用方式是stdcall,參數必須從右到左入棧,因此咱們先將uType參數入棧,範例中該參數的值是MB_OK+MB_ICONINFORMATION,即PUSH MB_OK+MB_ICONINFORMATION,而後再將lpCaption,lpText,hWnd依次入棧.最後才使用CALL指令調用MessageBox函數。orm
範例3:用asm代碼調用register方式的函數.StrLen的聲明爲:function StrLen(const Str: PChar): Cardinal; 它的調用方式是默認的register方式.blog
procedure TForm1.Button3Click(Sender: TObject); var Str:PChar; iLen:Integer; begin Str:='abcdefghijklm'; asm MOV EAX, Str //用EAX傳遞第一個參數 CALL StrLen MOV iLen,EAX end; ShowMessage(IntToStr(iLen)); end;