ตัวอย่างการใช้แอสเซมบลีใน Delphi
-----ยังเป็นนักเรียนปีที่สองตามตัวอย่างที่แล้ว 555 ตอนผมเขียนโปรแกรมเละเทะนิดหน่อย ขออภัยด้วยนะครับ :)
การใช้แอสเซมบลีสำหรับการเขียนโปรแกรมแบบไฮบริดใน Delphi นั้นสะดวกเป็นพิเศษ ด้วยวิธีนี้ เมื่อคุณต้องการได้รับประสิทธิภาพ คุณสามารถเลือกแอสเซมบลีได้ แต่สำหรับงานส่วนใหญ่ คุณยังคงเพลิดเพลินกับความสะดวกสบายของการเขียนโปรแกรมเชิงภาพและเชิงวัตถุ ในภาษา Delphi โดยใช้ส่วนของโปรแกรม asm...end เพื่อเขียนส่วนของโค้ดแอสเซมบลี ตัวแปรภาษาระดับสูงสามารถเรียกได้ในส่วนของโค้ดแอสเซมบลี สิ่งที่คุณต้องใส่ใจคือการปกป้องตัวแปรรีจิสเตอร์บางตัว และ จากนั้นรายละเอียดและสิ่งที่ควรทำ การรวบรวมด้านล่างจะแตกต่างออกไป ดูตัวอย่างนี้
เรามาพูดถึงความรู้ทั่วไปกันก่อน:
1. มีสองวิธีในการเรียกแอสเซมบลีใน Delphi
เช่นเดียวกับ---
ขั้นตอน TForm1.DrawRain;
var
x1,y1,x2,y2,d,i:จำนวนเต็ม;
start//โปรแกรม delphi เริ่มทำงาน
สำหรับ i:=0 ถึง 100 ทำ
เริ่ม
x1:=สุ่ม(537);
y1:=สุ่ม(280);
d:=สุ่ม(7);
asm//แอสเซมบลีแบบฝังเริ่มต้นขึ้น
ดัน eax
mov eax,x1
ซับบีเอ็กซ์,ดี
mov x2,eax
mov eax,y1
เพิ่ม eax,d
mov y2,eax
ป๊อป อีเอ็กซ์
end;;//สิ้นสุดการประกอบแบบฝัง
ครั้ง:=ครั้ง+1;
DrawLine2(x1,y1,x2,y2,clmedGray);
รอ();
ถ้า (i div 2)=0 แล้ว DrawLine2(x1,y1,x2,y2,clwindow);
จบ;
end;//โปรแกรม delphi สิ้นสุด
มีอีกวิธีหนึ่งในการลบ start...end ภายนอกและเข้าสู่ชุดประกอบโดยตรงผ่าน asm...end
ขั้นตอน TForm1.Wait();
asm//แอสเซมบลีแบบฝังเริ่มต้นขึ้น
ดัน eax
mov eax,0
@ลูป:
เพิ่ม eax,1
ซีเอ็มพี อีเอ็กซ์,1000000
เจนซ์ @loop
ป๊อป อีเอ็กซ์
end;//สิ้นสุดการประกอบแบบอินไลน์
2. ใช้ตัวแปรเดลฟีในการประกอบ
หากคุณดูตัวอย่างโค้ดแรก จะเข้าใจได้ง่าย:
asm//แอสเซมบลีแบบฝังเริ่มต้นขึ้น
ดัน eax
mov eax,x1 //x1 เป็นตัวแปรโลคัลเดลฟี ซึ่งใช้เป็นค่าที่นี่
ซับบีเอ็กซ์,ดี
mov x2,eax //x2 เป็นตัวแปรท้องถิ่นของ delphi และยังใช้เป็นที่อยู่หน่วยความจำด้วย
mov eax,y1
เพิ่ม eax,d
mov y2,eax
ป๊อป อีเอ็กซ์
end;;//สิ้นสุดการประกอบแบบฝัง
3. รายละเอียดต่าง ๆ ของการรวบรวม
ฉันจะไม่โพสต์ตัวอย่าง เรามาเปรียบเทียบกันเอง
@ลูป:
-
เจนซ์ @loop
นอกจากนี้ int Interrupt ส่วนใหญ่อาจไม่สามารถใช้ได้ ฉันยังไม่ได้ลอง และฉันไม่เห็นข้อมูลใดๆ เลย ใครรู้ช่วยส่งข้อความมาหน่อยค่ะ ขอขอบคุณล่วงหน้า.
ด้านล่างนี้เป็นตัวอย่างขนาดใหญ่ของเอฟเฟ็กต์ภาพเคลื่อนไหว เพราะผมเพิ่งเริ่มเรียนรู้ความรู้นี้ในอดีต ประสบการณ์ของผมจึงหยาบมาก เป็นฉากฝนตกต่อเนื่องในป่าเล็กๆ --- มีปัญหาหลายอย่าง ประการแรกคือ ไม่ได้ใช้คำสั่งจุดลอยตัว (ผมจะแนบตัวอย่างคำสั่งจุดลอยตัวมาลองทีหลัง ) ในขณะนั้นยังไม่ทราบอัลกอริธึมบางอย่าง และผลลัพธ์ที่ได้คือภาพที่ค่อนข้างซ้ำซากจำเจ ประการที่สอง การประสานกันระหว่างทิวทัศน์ยังไม่ดีพอ ตัวอย่างเช่น ต้นไม้ไม่ได้รับการปกป้องอย่างมีประสิทธิภาพ และต่อมาก็ "ออกดอก" ท่ามกลางสายฝน :)
แต่ฉันยังคงยกตัวอย่าง อย่าหัวเราะเยาะฉัน ประการแรก ฉันไม่มีเวลาเขียนตัวอย่างในส่วนนี้ ประการที่สอง หากคุณเรียนรู้วิธีใช้ Assembly ใน Delphi ก็ยังสามารถอธิบายปัญหาบางอย่างได้ ยิ่งไปกว่านั้น แอปพลิเคชั่นนี้หลีกเลี่ยงไม่ได้ในสื่อทั่วไป มันถูกกล่าวถึงเป็นครั้งคราวในการเขียนโปรแกรมขั้นสูง แต่ถ้าคุณต้องการที่จะเชี่ยวชาญ คุณจะต้องฝึกฝนด้วยตัวเองเป็นส่วนใหญ่ :)
หน่วย หน่วยที่ 1;
อินเตอร์เฟซ
การใช้งาน
Windows, ข้อความ, SysUtils, ตัวแปร, คลาส, กราฟิก, การควบคุม, แบบฟอร์ม,
กล่องโต้ตอบ, ExtCtrls, เมนู, ExtDlgs, FileCtrl, StdCtrls, ComCtrls, ImgList;
พิมพ์
TForm1 = คลาส (TForm)
เมนูหลัก1: TMainMenu;
ไฟล์ 1: TMenuItem;
Exit1: TMenuItem;
N1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
g1: TMenuItem;
Spring1: TMenuItem;
Summer1: TMenuItem;
Autumn1: TMenuItem;
Winter1: TMenuItem;
StatusBar1: TStatusBar;
ext1: TMenuItem;
ตัวจับเวลา 1: TTimer;
ขั้นตอน Exit1Click (ผู้ส่ง: TObject);
ขั้นตอน About1Click (ผู้ส่ง: TObject);
ขั้นตอน Spring1Click (ผู้ส่ง: TObject);
ขั้นตอน FormCreate (ผู้ส่ง: TObject);
ขั้นตอน Summer1Click (ผู้ส่ง: TObject);
ขั้นตอน Autumn1Click (ผู้ส่ง: TObject);
ขั้นตอน Winter1Click (ผู้ส่ง: TObject);
ขั้นตอน ext1Click (ผู้ส่ง: TObject);
ส่วนตัว
ขั้นตอน DrawLine1(x1,y1,x2,y2:integer;icolor:TColor);// x2>x1 และ y2>y1
ขั้นตอน DrawLine2(x1,y1,x2,y2:integer;icolor:TColor);// x2<x1 และ y2>y1
ขั้นตอน DrawLine3(x1,y1,x2,y2:integer;iColor:TColor);// x1=x2 หรือ y1=y2
ขั้นตอน DrawRain;
ขั้นตอน DrawTree (x, y, ความสูง: จำนวนเต็ม);
ขั้นตอน Timer1Timer (ผู้ส่ง: TObject);
ขั้นตอนการวาดชัดเจน;
ขั้นตอนรอ ();
{ประกาศส่วนตัว}
สาธารณะ
{ประกาศสาธารณะ}
จบ;
var
แบบฟอร์ม 1: TForm1;
ครั้ง:โสด;
การดำเนินการ
ใช้ Unit3, Unit5;
{$R *.dfm}
ขั้นตอน TForm1.Wait();
asm
ดัน eax
mov eax,0
@ลูป:
เพิ่ม eax,1
ซีเอ็มพี อีเอ็กซ์,1000000
เจนซ์ @loop
ป๊อป อีเอ็กซ์
จบ;
ขั้นตอน TForm1.DrawLine1(x1,y1,x2,y2:integer;iColor:TColor);
const i:จำนวนเต็ม=1;
var j,k1,k2,d:จำนวนเต็ม;
เริ่ม
if((x2-x1)<=0)or((y2-y1)<=0) จากนั้นออก;
สำหรับ j:=0 ถึง (x2-x1) ทำ
เริ่ม
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.วงรี(x1,y1,x1+2,y1+2);
form1.Canvas.วงรี(x1-1,y1-1,x1+1,y1+1);
ถ้า ((x2-x1)=0)หรือ((y2-y1)=0) แล้วออก;
asm
ดัน eax
pushebx
พุชเทคx
ดัน edx
mov ecx,0
mov eax,x2
ซับบีเอ็กซ์,x1
mov ebx,y2
ย่อย ebx,y1
mov d,ebx
mov edx,0
div ง
mov k2,eax
mov eax,y2
ย่อย eax,y1
mov ebx,x2
ย่อย ebx,x1
mov d,ebx
mov edx,0
div ง
mov k1,eax
mov eax,x1
@ ลูป2:
เพิ่ม eax ฉัน
incx
cmpecx,k2
เจบี @loop2
mov x1,eax
mov eax,y1
@ ลูป1:
เพิ่ม eax ฉัน
incx
cmpecx,k1
เจบี @loop1
mov y1,eax
ป๊อป เอ็ดเอ็กซ์
ป๊อปเอ็กซ์
ป๊อป ebx
ป๊อป อีเอ็กซ์
จบ;
สิ้นสุด;//สิ้นสุดสำหรับ
จบ;
ขั้นตอน TForm1.DrawLine2(x1,y1,x2,y2:integer;icolor:TColor);
const i:จำนวนเต็ม=1;
var j,k1,k2,d:จำนวนเต็ม;
เริ่ม
if((x1-x2)<=0)หรือ((y2-y1)<=0) จากนั้นออก;
สำหรับ j:=0 ถึง (x1-x2) ทำ
เริ่ม
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.วงรี(x1,y1,x1+2,y1+2);
form1.Canvas.วงรี(x1-1,y1-1,x1+1,y1+1);
ถ้า ((x1-x2)=0)หรือ((y2-y1)=0) แล้วออก;
asm
ดัน eax
pushebx
พุชเทคx
ดัน edx
mov ecx,0
mov eax,x1
ซับบีเอ็กซ์,x2
mov ebx,y2
ย่อย ebx,y1
mov d,ebx
mov edx,0
div ง
mov k2,eax
mov eax,y2
ย่อย eax,y1
mov ebx,x1
ย่อย ebx,x2
mov d,ebx
mov edx,0
div ง
mov k1,eax
mov eax,x1
@ ลูป2:
ย่อย eax, i
incx
cmpecx,k2
เจบี @loop2
mov x1,eax
mov eax,y1
@ ลูป1:
เพิ่ม eax ฉัน
incx
cmpecx,k1
เจบี @loop1
mov y1,eax
ป๊อป เอ็ดเอ็กซ์
ป๊อปเอ็กซ์
ป๊อป ebx
ป๊อป อีเอ็กซ์
จบ;
สิ้นสุด;//สิ้นสุดสำหรับ
จบ;
ขั้นตอน TForm1.DrawLine3(x1,y1,x2,y2:integer;icolor:TColor);
var j:จำนวนเต็ม;
เริ่ม
if((x2-x1)<>0)และ((y2-y1)<>0) จากนั้นออก;
ถ้า (x2-x1)=0 แล้ว
สำหรับ j:=0 ถึง (y2-y1) ทำ
เริ่ม
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.วงรี(x1-1,y1-1,x1+1,y1+1);
ถ้า (y2-y1)=0 ให้ออก;
asm
ดัน eax
mov eax,y1
รวม eax
mov y1,eax
ป๊อป อีเอ็กซ์
จบ;
สิ้นสุด//สิ้นสุดสำหรับ
อย่างอื่นสำหรับ j:=0 ถึง (x2-x1) ทำ
เริ่ม
form1.Canvas.Pen.Color:=icolor;
form1.Canvas.วงรี(x1-1,y1-1,x1+1,y1+1);
ถ้า (x2-x1)=0 ให้ออก;
asm
ดัน eax
mov eax,x1
รวม eax
mov x1,eax
ป๊อป อีเอ็กซ์
จบ;
สิ้นสุด;//สิ้นสุดสำหรับ
จบ;
ขั้นตอน TForm1.Timer1Timer (ผู้ส่ง: TObject);
เริ่ม
จบ;
ขั้นตอน TForm1.DrawRain;
var
x1,y1,x2,y2,d,i:จำนวนเต็ม;
เริ่ม
สำหรับ i:=0 ถึง 100 ทำ
เริ่ม
x1:=สุ่ม(537);
y1:=สุ่ม(280);
d:=สุ่ม(7);
asm
ดัน eax
mov eax,x1
ซับบีเอ็กซ์,ดี
mov x2,eax
mov eax,y1
เพิ่ม eax,d
mov y2,eax
ป๊อป อีเอ็กซ์
จบ;
ครั้ง:=ครั้ง+1;
DrawLine2(x1,y1,x2,y2,clmedGray);
รอ();
ถ้า (i div 2)=0 แล้ว DrawLine2(x1,y1,x2,y2,clwindow);
จบ;
จบ;
ขั้นตอน TForm1.DrawTree (x, y, ความสูง: จำนวนเต็ม);
var
x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,d1:จำนวนเต็ม;
เริ่ม
asm
ดัน eax
pushebx
พุชเทคx
ดัน edx
mov eax ความสูง
mov edx,0
mov ecx,2
ไดเวคซ์
mov d1,eax
mov eax,x
mov ebx,y
ย่อย eax ความสูง
mov x1,eax
ย่อย ebx ความสูง
mov y1,ebx
เพิ่ม eax, ส่วนสูง
ใต้ทะเล,5
ย่อย ebx ความสูง
mov x2,eax
mov y2,ebx
mov eax,x
เพิ่ม eax,3
ย่อย ebx ความสูง
mov x3,eax
mov y3,ebx
เพิ่ม eax,8
เพิ่ม ebx ส่วนสูง
mov x4,eax
mov y4,ebx
เพิ่ม eax, ส่วนสูง
ใต้ทะเล,5
เพิ่ม ebx ส่วนสูง
mov x5,eax
mov y5,ebx
ป๊อป เอ็ดเอ็กซ์
ป๊อปเอ็กซ์
ป๊อป ebx
ป๊อป อีเอ็กซ์
จบ;
DrawLine2(x3,y3,x2-d1,y2,clcream);
DrawLine1(x3,y3,x4+d1,y4,clcream);
เส้นวาด3(x2-d1,y2,x2,y2,clcream);
เส้นลาก3(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,คลิครีม);
DrawLine1(x4-2,y4,x5,y5+2,คครีม);
Drawline3(x1,y1,x5,y5,clcream);
วาดไลน์3(x1,y1-1,x5,y5-1,clcream);
Drawline3(x,y5,x,y,clcream);
Drawline3(x,y,x+5,y,clcream);
เส้นลาก3(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);
จบ;
ขั้นตอน TForm1.Exit1Click (ผู้ส่ง: TObject);
เริ่ม
ปิด;
จบ;
ขั้นตอน TForm1.About1Click (ผู้ส่ง: TObject);
เริ่ม
form3.แสดง;
จบ;
ขั้นตอน TForm1.Spring1Click (ผู้ส่ง: TObject);
var i,k,j:จำนวนเต็ม;
เริ่ม
StatusBar1.Panels[1].text:='ฤดูใบไม้ผลิแห่งพายุ...';
form1.Canvas.Brush.Color:=clwindow;
form1.Canvas.FloodFill (1,1, clred, fsBorder);
สำหรับ i:=0 ถึง 10do
เริ่ม
k:=สุ่ม(10);
เจ:=สุ่ม(10);
เจ:=-เจ;
DrawTree(10+k*50,300+j*20,20);
จบ;
สำหรับ i:=0 ถึง 10 ทำ
เริ่ม
form1.Canvas.Brush.Color:=clwindow;
form1.Canvas.FloodFill (1,1, clgreen, fsBorder);
วาดเรน;
นอน(100);
จบ;
จบ;
ขั้นตอน TForm1.FormCreate (ผู้ส่ง: TObject);
เริ่ม
ครั้ง:=0;
form1.canvas.Brush.Color:=clwindow;
form1.caption:=form1.caption+' โปรดเลือก Pictype!... ';
จบ;
ขั้นตอน TForm1.drawClear;
var i,k:จำนวนเต็ม;
เริ่ม
form1.Canvas.Brush.Color:=clblack;
form1.Canvas.FloodFill (15,15, clcream, fsBorder);
สำหรับ i:=0 ถึง 5 ทำ
เริ่ม
k:=สุ่ม(300);
DrawLine3(20+k,1,20+k,307,clสีเหลือง);
DrawLine3(200+k,1,200+k,307,clสีเหลือง);
จบ;
จบ;
ขั้นตอน TForm1.Summer1Click (ผู้ส่ง: TObject);
เริ่ม
วาดชัดเจน;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'มหาสมุทรสีเขียว...เวลาพักผ่อน^_^!');
//วาดต้นไม้;
จบ;
ขั้นตอน TForm1.Autumn1Click (ผู้ส่ง: TObject);
เริ่ม
วาดชัดเจน;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'ใบไม้สีแดงและภูเขาหอม...กำลังพักผ่อน^_^!');
จบ;
ขั้นตอน TForm1.Winter1Click (ผู้ส่ง: TObject);
//var i,x,y:จำนวนเต็ม;
เริ่ม
วาดชัดเจน;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'Silver Snake Wax Elephant...ยังไม่เปิด^_^!');
จบ;
ขั้นตอน TForm1.ext1Click (ผู้ส่ง: TObject);
เริ่ม
form5.แสดง;
จบ;
จบ.
ต่อไปนี้เป็นโปรแกรมทดสอบที่แนบมาโดยใช้คำสั่งจุดลอยตัวในขณะนั้นยังไม่บรรลุผล :):
//สั่งให้ห้องสมุดตรวจสอบ :)
ขั้นตอน Tform1.xx;
var
xmax,ymax,x,y,a,b:เดี่ยว;
ฉัน, z: จำนวนเต็ม;
เริ่ม
ก:=2.0;ข:=10.0;
xmax:=image1.ความกว้าง;
ymax:=image1.Height;
สำหรับ i:=0 ถึง image1.Width ทำ
เริ่ม
asm
//.80x87
จบ
fld xmax // กด xmax ใน st (0)
เอฟดิฟ เอ
fchs //ให้ st(0)=-st(0)
แฟชั่นฉัน //st(0)=st(0)+i
fdiv b //st(0)=st(0)/b
fstp x //ใส่ st(0) ใน x โดยไม่มีป๊อปอัป
x
เอฟมูล x
fchs
แฟชั่น ymax
//frndint
//แฟบส์
fstp y
จบ;
x:=(i-xmax/2)/10;
y:=-x*x+ymax;
z:=trunc(z);
image1.canvas.วงรี(i-1,trunc(y)-1,i+1,trunc(y)+1);
//image1.Canvas.Pixels[x,y];
จบ;
จบ;
ฉันเลือกกระบวนการหนึ่ง 555 ตลกดี
คุณอาจจะนำสิ่งที่คุณออกไปและแบ่งปันประสบการณ์ของคุณ ฉันพร้อมที่จะฟัง :)
โปรด----