delphi与汇编
我一直認(rèn)為Delphi功能與C++相比毫不遜色,提供了豐富的控件和類(lèi)、全部API以及嵌入的匯編。最近小弟在把C版的Huffman壓縮改用Delphi寫(xiě)時(shí),順便“研究”了一下Delphi的位操作和嵌入式匯編,利用嵌入?yún)R編我們可以得到高效的程序代碼,完成一些Delphi沒(méi)有提供的底層功能。借貴報(bào)一方寶地與大家分享我的“研究”。
Delphi的位操作
每個(gè)學(xué)習(xí)C的朋友都會(huì)被告之C是“中級(jí)語(yǔ)言”,其位操作非常方便,而Pascal之流只適用于教學(xué)。但是Delphi中提供了一組位操作,可別以過(guò)去對(duì)Pascal的態(tài)度看Delphi。
* 按位的邏輯操作:
Delphi中的AND、OR、NOT可不僅僅只對(duì)邏輯表達(dá)式有作用,它們還可以操作數(shù);
AND:按位與,如:1 AND 2其結(jié)果為0
OR:按位或,如:1 OR 2其結(jié)果為3
Not:按位取反:如Not 1其結(jié)果對(duì)于有符號(hào)數(shù)是-2,對(duì)于無(wú)符號(hào)數(shù)是65534
另外,還有按位異或XOR:如:1 XOR 2結(jié)果為3
* 移位操作
Delphi提供了SHL和SHR進(jìn)行移位左移和右移:
例如:2 SHR1表示2按位右移一位結(jié)果為1。
* Delphi中的數(shù)
既然有位的操作就一定涉及到數(shù)的類(lèi)型:是有符號(hào)數(shù)(頭一位用0和1表示正負(fù))還是無(wú)符號(hào)數(shù)。
Delphi中:Shortint(8位)、Smallint(16位)、Longint(32位)、Integer(32位)、Int64(64位)是有符號(hào)數(shù);而B(niǎo)yte(8位)、Word(16位)、Longword(32位)是無(wú)符號(hào)數(shù)。它們之間可以像C一樣強(qiáng)制轉(zhuǎn)換。例如:Smallint類(lèi)型的-1轉(zhuǎn)換成Word類(lèi)型就是65535。轉(zhuǎn)換方法是Word(-1)。
怎樣,夠全吧^_^!什么還不夠……!?Delphi還有一招,接招吧……
Delphi的嵌入式匯編
Delphi中提供了幾乎全部常用匯編指令的支持:MOV、JE、JMP、CMP、SHL、SHR、SAL、SAR、POP、PUSH、HLT……自己去查吧。至于INT也能識(shí)別,不過(guò)非法操作或死機(jī)可別找我(在最早的Windows95中用Delphi 3似乎可以正確運(yùn)行中斷,但Windows 95 OEM、Windows 98就不對(duì)了,大概是16位模塊的問(wèn)題,還搞不清楚)。
* 嵌入式匯編的格式
Delphi是使用ASM……END來(lái)標(biāo)志匯編語(yǔ)句
如: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
以及協(xié)處理器寄存器堆棧 ST
* 使用匯編前的工作
教匯編的老師一再?gòu)?qiáng)調(diào)使用匯編要保存寄存器現(xiàn)場(chǎng)(保存使用前的寄存器狀態(tài),使用Push壓棧和Pop從棧中彈出),不過(guò)這一切對(duì)于Delphi的嵌入式匯編是沒(méi)有必要的(除非你自己要使用Push和Pop),因?yàn)镈elphi已經(jīng)幫你做了,不必?fù)?dān)心會(huì)使數(shù)據(jù)丟掉。
* Delphi嵌入式匯編的使用方式
1.在一般函數(shù)過(guò)程中使用匯編
匯編程序段可以嵌套于其它過(guò)程中:如:
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;
這個(gè)程序段是把16位的變量I進(jìn)行左移,然后把結(jié)果用Mov &I,ax語(yǔ)句放入I變量所在地址返回值。最后顯示I 的值是2。
2.獨(dú)立的匯編程序段
匯編程序段也可以單獨(dú)寫(xiě)成函數(shù)或過(guò)程。這就涉及到參數(shù)的傳遞與結(jié)果的返回。首先Delphi對(duì)于函數(shù)的返回有一個(gè)約定:
即:整型數(shù)據(jù):8位的用AL返回,16位的用AX返回,32位的用EAX返回;
實(shí)型:用ST(0)返回
指針:用EAX返回
長(zhǎng)字符串:用EAX返回其所在地址
變量:可用@Result返回
例如:一個(gè)用匯編的求和函數(shù)
function _Sum(X, Y: Integer): Integer;
asm
MOV EAX,X //把32位的數(shù)放入EAX
ADD EAX,Y //進(jìn)行加法運(yùn)算
MOV @Result,EAX //返回X+Y
end;
一個(gè)把字符轉(zhuǎn)化為大寫(xiě)的函數(shù)例子
function _UpCase( ch : Char ) : Char;
asm
CMP AL,`a'
JB @@exit
CMP AL,`z'
JA @@exit
SUB AL,`a' -`A'
@@exit:
end;
值得注意的是第二個(gè)例子中,沒(méi)有象第一個(gè)那樣把參數(shù)用語(yǔ)句放到寄存器中,這是由于Delphi中默認(rèn)的把Byte(Char)類(lèi)型放在AL中,不需要用Mov語(yǔ)句,但是這種函數(shù)不能是類(lèi)的成員,否則結(jié)果會(huì)出錯(cuò)。
3.在匯編中調(diào)用其它過(guò)程
匯編語(yǔ)句中的Call語(yǔ)句,可以用于調(diào)用其它過(guò)程,既可以是其它匯編程序段也可以是Delphi中的標(biāo)準(zhǔn)過(guò)程:
例如:假設(shè)新建一個(gè)窗體并在上面加了一個(gè)按鈕,在Click事件中寫(xiě)入以下代碼
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(`ok');
end;
再寫(xiě)一個(gè)過(guò)程_X
function TForm1._x(var i:smallint):integer;
asm
call button1click
end;
執(zhí)行_x的結(jié)果就可以顯示消息框。
* 匯編的調(diào)試
編好了程序,沒(méi)錯(cuò),還好,如果有錯(cuò),就得用到調(diào)試工具:如變量的跟蹤、斷點(diǎn)、堆棧查看……對(duì)于匯編還可以用View菜單的Debug Windows的CPU窗口跟蹤。
OK!就談到這,希望對(duì)使用Delphi的朋友有點(diǎn)幫助。
Delphi的位操作
每個(gè)學(xué)習(xí)C的朋友都會(huì)被告之C是“中級(jí)語(yǔ)言”,其位操作非常方便,而Pascal之流只適用于教學(xué)。但是Delphi中提供了一組位操作,可別以過(guò)去對(duì)Pascal的態(tài)度看Delphi。
* 按位的邏輯操作:
Delphi中的AND、OR、NOT可不僅僅只對(duì)邏輯表達(dá)式有作用,它們還可以操作數(shù);
AND:按位與,如:1 AND 2其結(jié)果為0
OR:按位或,如:1 OR 2其結(jié)果為3
Not:按位取反:如Not 1其結(jié)果對(duì)于有符號(hào)數(shù)是-2,對(duì)于無(wú)符號(hào)數(shù)是65534
另外,還有按位異或XOR:如:1 XOR 2結(jié)果為3
* 移位操作
Delphi提供了SHL和SHR進(jìn)行移位左移和右移:
例如:2 SHR1表示2按位右移一位結(jié)果為1。
* Delphi中的數(shù)
既然有位的操作就一定涉及到數(shù)的類(lèi)型:是有符號(hào)數(shù)(頭一位用0和1表示正負(fù))還是無(wú)符號(hào)數(shù)。
Delphi中:Shortint(8位)、Smallint(16位)、Longint(32位)、Integer(32位)、Int64(64位)是有符號(hào)數(shù);而B(niǎo)yte(8位)、Word(16位)、Longword(32位)是無(wú)符號(hào)數(shù)。它們之間可以像C一樣強(qiáng)制轉(zhuǎn)換。例如:Smallint類(lèi)型的-1轉(zhuǎn)換成Word類(lèi)型就是65535。轉(zhuǎn)換方法是Word(-1)。
怎樣,夠全吧^_^!什么還不夠……!?Delphi還有一招,接招吧……
Delphi的嵌入式匯編
Delphi中提供了幾乎全部常用匯編指令的支持:MOV、JE、JMP、CMP、SHL、SHR、SAL、SAR、POP、PUSH、HLT……自己去查吧。至于INT也能識(shí)別,不過(guò)非法操作或死機(jī)可別找我(在最早的Windows95中用Delphi 3似乎可以正確運(yùn)行中斷,但Windows 95 OEM、Windows 98就不對(duì)了,大概是16位模塊的問(wèn)題,還搞不清楚)。
* 嵌入式匯編的格式
Delphi是使用ASM……END來(lái)標(biāo)志匯編語(yǔ)句
如: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
以及協(xié)處理器寄存器堆棧 ST
* 使用匯編前的工作
教匯編的老師一再?gòu)?qiáng)調(diào)使用匯編要保存寄存器現(xiàn)場(chǎng)(保存使用前的寄存器狀態(tài),使用Push壓棧和Pop從棧中彈出),不過(guò)這一切對(duì)于Delphi的嵌入式匯編是沒(méi)有必要的(除非你自己要使用Push和Pop),因?yàn)镈elphi已經(jīng)幫你做了,不必?fù)?dān)心會(huì)使數(shù)據(jù)丟掉。
* Delphi嵌入式匯編的使用方式
1.在一般函數(shù)過(guò)程中使用匯編
匯編程序段可以嵌套于其它過(guò)程中:如:
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;
這個(gè)程序段是把16位的變量I進(jìn)行左移,然后把結(jié)果用Mov &I,ax語(yǔ)句放入I變量所在地址返回值。最后顯示I 的值是2。
2.獨(dú)立的匯編程序段
匯編程序段也可以單獨(dú)寫(xiě)成函數(shù)或過(guò)程。這就涉及到參數(shù)的傳遞與結(jié)果的返回。首先Delphi對(duì)于函數(shù)的返回有一個(gè)約定:
即:整型數(shù)據(jù):8位的用AL返回,16位的用AX返回,32位的用EAX返回;
實(shí)型:用ST(0)返回
指針:用EAX返回
長(zhǎng)字符串:用EAX返回其所在地址
變量:可用@Result返回
例如:一個(gè)用匯編的求和函數(shù)
function _Sum(X, Y: Integer): Integer;
asm
MOV EAX,X //把32位的數(shù)放入EAX
ADD EAX,Y //進(jìn)行加法運(yùn)算
MOV @Result,EAX //返回X+Y
end;
一個(gè)把字符轉(zhuǎn)化為大寫(xiě)的函數(shù)例子
function _UpCase( ch : Char ) : Char;
asm
CMP AL,`a'
JB @@exit
CMP AL,`z'
JA @@exit
SUB AL,`a' -`A'
@@exit:
end;
值得注意的是第二個(gè)例子中,沒(méi)有象第一個(gè)那樣把參數(shù)用語(yǔ)句放到寄存器中,這是由于Delphi中默認(rèn)的把Byte(Char)類(lèi)型放在AL中,不需要用Mov語(yǔ)句,但是這種函數(shù)不能是類(lèi)的成員,否則結(jié)果會(huì)出錯(cuò)。
3.在匯編中調(diào)用其它過(guò)程
匯編語(yǔ)句中的Call語(yǔ)句,可以用于調(diào)用其它過(guò)程,既可以是其它匯編程序段也可以是Delphi中的標(biāo)準(zhǔn)過(guò)程:
例如:假設(shè)新建一個(gè)窗體并在上面加了一個(gè)按鈕,在Click事件中寫(xiě)入以下代碼
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(`ok');
end;
再寫(xiě)一個(gè)過(guò)程_X
function TForm1._x(var i:smallint):integer;
asm
call button1click
end;
執(zhí)行_x的結(jié)果就可以顯示消息框。
* 匯編的調(diào)試
編好了程序,沒(méi)錯(cuò),還好,如果有錯(cuò),就得用到調(diào)試工具:如變量的跟蹤、斷點(diǎn)、堆棧查看……對(duì)于匯編還可以用View菜單的Debug Windows的CPU窗口跟蹤。
OK!就談到這,希望對(duì)使用Delphi的朋友有點(diǎn)幫助。
總結(jié)
- 上一篇: Delphi中高级DLL的编写和调用
- 下一篇: 严格地说来的zhajinhuagame