我一直認爲Delphi功能與C++相比絕不遜色,提供了豐富的控件和類、所有API以及嵌入的彙編。最近小弟在把C版的Huffman壓縮改用Delphi寫時,順便「研究」了一下Delphi的位操做和嵌入式彙編,利用嵌入彙編咱們能夠獲得高效的程序代碼,完成一些Delphi沒有提供的底層功能。借貴報一方寶地與你們分享個人「研究」。
Delphi的位操做
每一個學習C的朋友都會被告之C是「中級語言」,其位操做很是方便,而Pascal之流只適用於教學。可是Delphi中提供了一組位操做,可別以過去對Pascal的態度看Delphi。
* 按位的邏輯操做:
Delphi中的AND、OR、NOT可不單單隻對邏輯表達式有做用,它們還能夠操做數;
AND:按位與,如:1 AND 2其結果爲0
OR:按位或,如:1 OR 2其結果爲3
Not:按位取反:如Not 1其結果對於有符號數是-2,對於無符號數是65534
另外,還有按位異或XOR:如:1 XOR 2結果爲3
* 移位操做
Delphi提供了SHL和SHR進行移位左移和右移:
例如:2 SHR1表示2按位右移一位結果爲1。
* Delphi中的數
既然有位的操做就必定涉及到數的類型:是有符號數(頭一位用0和1表示正負)仍是無符號數。
Delphi中:Shortint(8位)、Smallint(16位)、Longint(32位)、Integer(32位)、Int64(64位)是有符號數;而Byte(8位)、Word(16位)、Longword(32位)是無符號數。它們之間能夠像C同樣強制轉換。例如:Smallint類型的-1轉換成Word類型就是65535。轉換方法是Word(-1)。
怎樣,夠全吧^_^!什麼還不夠……!?Delphi還有一招,接招吧……
Delphi的嵌入式彙編
Delphi中提供了幾乎所有經常使用匯編指令的支持:MOV、JE、JMP、CMP、SHL、SHR、SAL、SAR、POP、PUSH、HLT……本身去查吧。至於INT也能識別,不過非法操做或死機可別找我(在最先的Windows95中用Delphi 3彷佛能夠正確運行中斷,但Windows 95 OEM、Windows 98就不對了,大概是16位模塊的問題,還搞不清楚)。
* 嵌入式彙編的格式
Delphi是使用ASM……END來標誌彙編語句
如:ASM
mov al,1
mov bl,al
END;
* 可操做的寄存器
Delphi可用匯編管理如下寄存器:
32位寄存器EAX EBX ECX EDX ESP EBP ESI EDI
16位寄存器AX BX CX DX SP BP SI DI
8位寄存器AL BL CL DL AH BH CH DH
16位段寄存器CS DS SS ES
以及協處理器寄存器堆棧 ST
* 使用匯編前的工做
教彙編的老師一再強調使用匯編要保存寄存器現場(保存使用前的寄存器狀態,使用Push壓棧和Pop從棧中彈出),不過這一切對於Delphi的嵌入式彙編是沒有必要的(除非你本身要使用Push和Pop),由於Delphi已經幫你作了,沒必要擔憂會使數據丟掉。
* Delphi嵌入式彙編的使用方式
1.在通常函數過程當中使用匯編
彙編程序段能夠嵌套於其它過程當中:如:
procedure TForm1.Button1Click(Sender: TObject);
var i:smallint;
begin
i:=1;
asm
mov ax,i
sal ax,1
mov &i,ax
end;
showmessage(inttostr(i));
end;
這個程序段是把16位的變量I進行左移,而後把結果用Mov &I,ax語句放入I變量所在地址返回值。最後顯示I 的值是2。
2.獨立的彙編程序段
彙編程序段也能夠單獨寫成函數或過程。這就涉及到參數的傳遞與結果的返回。首先Delphi對於函數的返回有一個約定:
即:整型數據:8位的用AL返回,16位的用AX返回,32位的用EAX返回;
實型:用ST(0)返回
指針:用EAX返回
長字符串:用EAX返回其所在地址
變量:可用@Result返回
例如:一個用匯編的求和函數
function _Sum(X, Y: Integer): Integer;
asm
MOV EAX,X //把32位的數放入EAX
ADD EAX,Y //進行加法運算
MOV @Result,EAX //返回X+Y
end;
一個把字符轉化爲大寫的函數例子
function _UpCase( ch : Char ) : Char;
asm
CMP AL,`a'
JB @@exit
CMP AL,`z'
JA @@exit
SUB AL,`a' -`A'
@@exit:
end;
值得注意的是第二個例子中,沒有象第一個那樣把參數用語句放到寄存器中,這是因爲Delphi中默認的把Byte(Char)類型放在AL中,不須要用Mov語句,可是這種函數不能是類的成員,不然結果會出錯。
3.在彙編中調用其它過程
彙編語句中的Call語句,能夠用於調用其它過程,既能夠是其它彙編程序段也能夠是Delphi中的標準過程:
例如:假設新建一個窗體並在上面加了一個按鈕,在Click事件中寫入如下代碼
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(`ok');
end;
再寫一個過程_X
function TForm1._x(var i:smallint):integer;
asm
call button1click
end;
執行_x的結果就能夠顯示消息框。
* 彙編的調試
編好了程序,沒錯,還好,若是有錯,就得用到調試工具:如變量的跟蹤、斷點、堆棧查看……對於彙編還能夠用View菜單的Debug Windows的CPU窗口跟蹤。
OK!就談到這,但願對使用Delphi的朋友有點幫助編程