Delphi中使用彙編例子
-----也是大二的,接著上一個例子。呵呵,程式當時寫的有點亂,請原諒:)。
Delphi中使用彙編進行混合編程,是異常的方便。如此,當你希望得到效率的時候,你可選擇彙編,然而大部分工作,你仍是享受著可視化、物件導向程式設計的方便。 delphi的語言,透過使用asm...end程式段寫彙編程式碼部分,在彙編程式碼段中可以呼叫高階語言的變數;你需要注意的是,保護某些暫存器變量,然後呢,某些細節和dos下的彙編不同。大家看這個例子。
先大體說說一些小知識:
一,Delphi呼叫彙編,有兩種方式。
一如---
PRocedure TForm1.DrawRain;
var
x1,y1,x2,y2,d,i:integer;
begin//delphi程式開始
for i:=0 to 100 do
begin
x1:=random(537);
y1:=random(280);
d:=random(7);
asm//內嵌彙編開始
push eax
mov eax,x1
sub eax,d
mov x2,eax
mov eax,y1
add eax,d
mov y2,eax
pop eax
end;;//內嵌彙編結束
times:=times+1;
drawLine2(x1,y1,x2,y2,clmedGray);
wait();
if (i div 2)=0 then drawLine2(x1,y1,x2,y2,clwindow);
end;
end;//delphi程式結束
還有一種,把外層的begin...end去掉,透過asm...end直接進入彙編。
procedure TForm1.Wait();
asm//內嵌彙編開始
push eax
mov eax,0
@loop:
add eax,1
cmp eax,1000000
jnz @loop
pop eax
end;//內嵌彙編結束
二,在彙編中使用delphi的變數
大家看第一段程式碼的例子,很容易懂:
asm//內嵌彙編開始
push eax
mov eax,x1 //x1是delphi局部變量,此處用作值
sub eax,d
mov x2,eax //x2是delphi局部變量,又用作記憶體位址
mov eax,y1
add eax,d
mov y2,eax
pop eax
end;;//內嵌彙編結束
三,彙編的不同細節
例子不帖了,大家自己比較了,如
@loop:
//...
jnz @loop
另外,大部分int中斷可能不能用,我沒有試通,也沒看到什麼資料上介紹過。誰知道,給我發個訊息好嗎?謝謝了先。
下面是一個比較大的例子,是動畫效果。因為以前剛開始學這方面的知識,做的很粗糙。是一個小樹林裡,不停的下著雨的場景---很多問題,表現突出的是,首先浮點指令沒有會用(我在後面會附上有待繼續嘗試的浮點數指令的測試例子),有些演算法當時還不會,結果畫面比較單調,其次,對景物間的協調不夠好,例如樹沒有有效保護,後來就被雨「花」了:)。
但還是做例子了,大家別笑我,一來沒時間寫這方面的例子了,二來,學Delphi中的彙編使用,它還是可以說明某些問題的。而且,一般的資料上,是迴避這個應用的,個別的高級編程中,偶爾提及,可大家要想掌握,大都得要自己多實踐,這個例子可以個給你許多教訓:)。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Menus, ExtDlgs, FileCtrl, StdCtrls, ComCtrls, ImgList;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
N1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
g1: TMenuItem;
Spring1: TMenuItem;
Summer1: TMenuItem;
Autumn1: TMenuItem;
Winter1: TMenuItem;
StatusBar1: TStatusBar;
ext1: TMenuItem;
Timer1: TTimer;
procedure Exit1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure Spring1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Summer1Click(Sender: TObject);
procedure Autumn1Click(Sender: TObject);
procedure Winter1Click(Sender: TObject);
procedure ext1Click(Sender: TObject);
private
procedure DrawLine1(x1,y1,x2,y2:integer;icolor:TColor);// x2>x1 and y2>y1
procedure DrawLine2(x1,y1,x2,y2:integer;icolor:TColor);// x2<x1 and y2>y1
procedure DrawLine3(x1,y1,x2,y2:integer;iColor:TColor);// x1=x2 or y1=y2
procedure DrawRain;
procedure DrawTree(x,y,height:integer);
procedure Timer1Timer(sender:TObject);
procedure drawClear;
procedure Wait();
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
times:single;
implementation
uses Unit3,Unit5;
{$R *.dfm}
procedure TForm1.Wait();
asm
push eax
mov eax,0
@loop:
add eax,1
cmp eax,1000000
jnz @loop
pop eax
end;
procedure TForm1.DrawLine1(x1,y1,x2,y2:integer;iColor:TColor);
const i:integer=1;
var j,k1,k2,d:integer;
begin
if((x2-x1)<=0)or((y2-y1)<=0) then exit;
for j:=0 to (x2-x1) do
begin
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.Ellipse(x1,y1,x1+2,y1+2);
form1.Canvas.Ellipse(x1-1,y1-1,x1+1,y1+1);
if ((x2-x1)=0)or((y2-y1)=0) then exit;
asm
push eax
push ebx
push ecx
push edx
mov ecx,0
mov eax,x2
sub eax,x1
mov ebx,y2
sub ebx,y1
mov d,ebx
mov edx,0
div d
mov k2,eax
mov eax,y2
sub eax,y1
mov ebx,x2
sub ebx,x1
mov d,ebx
mov edx,0
div d
mov k1,eax
mov eax,x1
@loop2:
add eax,i
inc ecx
cmp ecx,k2
jb @loop2
mov x1,eax
mov eax,y1
@loop1:
add eax,i
inc ecx
cmp ecx,k1
jb @loop1
mov y1,eax
pop edx
pop ecx
pop ebx
pop eax
end;
end;// end for
end;
procedure TForm1.DrawLine2(x1,y1,x2,y2:integer;icolor:TColor);
const i:integer=1;
var j,k1,k2,d:integer;
begin
if((x1-x2)<=0)or((y2-y1)<=0) then exit;
for j:=0 to (x1-x2) do
begin
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.Ellipse(x1,y1,x1+2,y1+2);
form1.Canvas.Ellipse(x1-1,y1-1,x1+1,y1+1);
if ((x1-x2)=0)or((y2-y1)=0) then exit;
asm
push eax
push ebx
push ecx
push edx
mov ecx,0
mov eax,x1
sub eax,x2
mov ebx,y2
sub ebx,y1
mov d,ebx
mov edx,0
div d
mov k2,eax
mov eax,y2
sub eax,y1
mov ebx,x1
sub ebx,x2
mov d,ebx
mov edx,0
div d
mov k1,eax
mov eax,x1
@loop2:
sub eax,i
inc ecx
cmp ecx,k2
jb @loop2
mov x1,eax
mov eax,y1
@loop1:
add eax,i
inc ecx
cmp ecx,k1
jb @loop1
mov y1,eax
pop edx
pop ecx
pop ebx
pop eax
end;
end;// end for
end;
procedure TForm1.DrawLine3(x1,y1,x2,y2:integer;icolor:TColor);
var j:integer;
begin
if((x2-x1)<>0)and((y2-y1)<>0) then exit;
if (x2-x1)=0 then
for j:=0 to (y2-y1) do
begin
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.Ellipse(x1-1,y1-1,x1+1,y1+1);
if (y2-y1)=0 then exit;
asm
push eax
mov eax,y1
inc eax
mov y1,eax
pop eax
end;
end// end for
else for j:=0 to (x2-x1) do
begin
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.Ellipse(x1-1,y1-1,x1+1,y1+1);
if (x2-x1)=0 then exit;
asm
push eax
mov eax,x1
inc eax
mov x1,eax
pop eax
end;
end;// end for
end;
procedure TForm1.Timer1Timer(sender:TObject);
begin
end;
procedure TForm1.DrawRain;
var
x1,y1,x2,y2,d,i:integer;
begin
for i:=0 to 100 do
begin
x1:=random(537);
y1:=random(280);
d:=random(7);
asm
push eax
mov eax,x1
sub eax,d
mov x2,eax
mov eax,y1
add eax,d
mov y2,eax
pop eax
end;
times:=times+1;
drawLine2(x1,y1,x2,y2,clmedGray);
wait();
if (i div 2)=0 then drawLine2(x1,y1,x2,y2,clwindow);
end;
end;
procedure TForm1.DrawTree(x,y,height:integer);
var
x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,d1:integer;
begin
asm
push eax
push ebx
push ecx
push edx
mov eax,height
mov edx,0
mov ecx,2
div ecx
mov d1,eax
mov eax,x
mov ebx,y
sub eax,height
mov x1,eax
sub ebx,height
mov y1,ebx
add eax,height
sub eax,5
sub ebx,height
mov x2,eax
mov y2,ebx
mov eax,x
add eax,3
sub ebx,height
mov x3,eax
mov y3,ebx
add eax,8
add ebx,height
mov x4,eax
mov y4,ebx
add eax,height
sub eax,5
add ebx,height
mov x5,eax
mov y5,ebx
pop edx
pop ecx
pop ebx
pop eax
end;
DrawLine2(x3,y3,x2-d1,y2,clcream);
DrawLine1(x3,y3,x4+d1,y4,clcream);
drawline3(x2-d1,y2,x2,y2,clcream);
drawline3(x4,y4,x4+d1,y4,clcream);
DrawLine2(x2,y2,x1,y1,clcream);
DrawLine1(x4,y4,x5,y5,clcream);
DrawLine2(x2+2,y2,x1,y1+2,clcream);
DrawLine1(x4-2,y4,x5,y5+2,clcream);
drawline3(x1,y1,x5,y5,clcream);
drawline3(x1,y1-1,x5,y5-1,clcream);
drawline3(x,y5,x,y,clcream);
drawline3(x,y,x+5,y,clcream);
drawline3(x+5,y5,x+5,y,clcream);
form1.Canvas.Brush.Color:=clgreen;
form1.Canvas.FloodFill(x,y1-5,clcream,fsBorder);
form1.Canvas.FloodFill(x+2,y-5,clcream,fsBorder);
end;
procedure TForm1.Exit1Click(Sender: TObject);
begin
close;
end;
procedure TForm1.About1Click(Sender: TObject);
begin
form3.Show;
end;
procedure TForm1.Spring1Click(Sender: TObject);
var i,k,j:integer;
begin
StatusBar1.Panels[1].text:='風雨之春...';
form1.Canvas.Brush.Color:=clwindow;
form1.Canvas.FloodFill(1,1,clred,fsBorder);
for i:=0 to 10do
begin
k:=random(10);
j:=random(10);
j:=-j;
drawTree(10+k*50,300+j*20,20);
end;
for i:=0 to 10 do
begin
form1.Canvas.Brush.Color:=clwindow;
form1.Canvas.FloodFill(1,1,clgreen,fsBorder);
drawRain;
sleep(100);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
times:=0;
form1.canvas.Brush.Color:=clwindow;
form1.caption:=form1.caption+' Please select the Pictype!... ';
end;
procedure TForm1.drawClear;
var i,k:integer;
begin
form1.Canvas.Brush.Color:=clblack;
form1.Canvas.FloodFill(15,15, clcream, fsBorder);
for i:=0 to 5 do
begin
k:=random(300);
DrawLine3(20+k,1,20+k,307,clyellow);
DrawLine3(200+k,1,200+k,307,clyellow);
end;
end;
procedure TForm1.Summer1Click(Sender: TObject);
begin
drawClear;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'綠色海洋...休息時間^_^!');
//DrawTree;
end;
procedure TForm1.Autumn1Click(Sender: TObject);
begin
drawClear;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'紅葉香山...正在休息^_^!');
end;
procedure TForm1.Winter1Click(Sender: TObject);
//var i,x,y:integer;
begin
drawClear;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'銀蛇臘象...暫時不開放^_^!');
end;
procedure TForm1.ext1Click(Sender: TObject);
begin
form5.Show;
end;
end.
以下是附帶的使用浮點數指令的測試程序,當時的原本,未達到效果的:):
//指令圖書館查的:)
procedure Tform1.xx;
var
xmax,ymax,x,y,a,b:single;
i,z:integer;
begin
a:=2.0;b:=10.0;
xmax:=image1.Width;
ymax:=image1.Height;
for i:=0 to image1.Width do
begin
asm
//.80x87
finit
fld xmax //push xmax in st(0)
fdiv a
fchs //let st(0)=-st(0)
fadd i //st(0)=st(0)+i
fdiv b //st(0)=st(0)/b
fstp x //put st(0) in x without pop
fld x
fmul x
fchs
fadd ymax
//frndint
//fabs
fstp y
end;
x:=(i-xmax/2)/10;
y:=-x*x+ymax;
z:=trunc(z);
image1.canvas.Ellipse(i-1,trunc(y)-1,i+1,trunc(y)+1);
//image1.Canvas.Pixels[x,y];
end;
end;
選的是其中一個過程,呵呵,見笑了。
大家不妨把自己的東西拿出來,經驗說一說,我準備洗耳恭聽:)。
請----