Examples of using assembly in Delphi
-----Also a sophomore, following the previous example. Haha, the program was a bit messy when I wrote it, please forgive me :).
Using assembly for hybrid programming in Delphi is unusually convenient. In this way, when you want to gain efficiency, you can choose assembly, but for most work, you still enjoy the convenience of visual and object-oriented programming. In Delphi language, by using the asm...end program segment to write the assembly code part, high-level language variables can be called in the assembly code segment; what you need to pay attention to is to protect certain register variables, and then, some details and dos The compilation below is different. Look at this example.
Let’s talk about some general knowledge first:
1. There are two ways to call assembly in Delphi.
Just like---
PRocedure TForm1.DrawRain;
var
x1,y1,x2,y2,d,i:integer;
begin//delphi program starts
for i:=0 to 100 do
begin
x1:=random(537);
y1:=random(280);
d:=random(7);
asm//embedded assembly starts
push eax
mov eax,x1
subeax,d
mov x2,eax
mov eax,y1
add eax,d
mov y2,eax
pop eax
end;;//end of embedded assembly
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 program ends
There is another way to remove the outer begin...end and directly enter assembly through asm...end.
procedure TForm1.Wait();
asm//embedded assembly starts
push eax
mov eax,0
@loop:
add eax,1
cmp eax,1000000
jnz @loop
pop eax
end;//end of inline assembly
2. Use delphi variables in assembly
If you look at the first code example, it is easy to understand:
asm//embedded assembly starts
push eax
mov eax,x1 //x1 is a delphi local variable, used as a value here
subeax,d
mov x2,eax //x2 is a delphi local variable and is also used as a memory address
mov eax,y1
add eax,d
mov y2,eax
pop eax
end;;//End of embedded assembly
3. Different details of the compilation
I won’t post the examples. Let’s compare them by ourselves. For example:
@loop:
//...
jnz @loop
In addition, most int interrupts may not be available. I have not tried it, and I have not seen any information on it. Who knows, please send me a message? Thank you in advance.
Below is a larger example of an animation effect. Because I just started to learn this knowledge in the past, my work was very rough. It is a scene of constant rain in a small forest---there are many problems, the most prominent one is that first of all, the floating point instructions are not used (I will attach test examples of floating point instructions to be tried later), Some algorithms were not yet known at the time, and the result was a rather monotonous picture. Secondly, the coordination between the scenery was not good enough. For example, the trees were not effectively protected and were later "flowered" by the rain :).
But I’m still giving an example. Don’t laugh at me. Firstly, I don’t have time to write examples in this area. Secondly, if you learn how to use assembly in Delphi, it can still explain certain problems. Moreover, this application is avoided in general materials. It is occasionally mentioned in some advanced programming, but if you want to master it, you mostly have to practice it yourself. This example can teach you a lot of lessons :).
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
pushebx
pushecx
push edx
mov ecx,0
mov eax,x2
subeax,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
incecx
cmpecx,k2
jb @loop2
mov x1,eax
mov eax,y1
@loop1:
add eax,i
incecx
cmpecx,k1
jb @loop1
mov y1,eax
pop edx
popecx
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
pushebx
pushecx
push edx
mov ecx,0
mov eax,x1
subeax,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
incecx
cmpecx,k2
jb @loop2
mov x1,eax
mov eax,y1
@loop1:
add eax,i
incecx
cmpecx,k1
jb @loop1
mov y1,eax
pop edx
popecx
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
subeax,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
pushebx
pushecx
push edx
mov eax,height
mov edx,0
mov ecx,2
divecx
mov d1,eax
mov eax,x
mov ebx,y
sub eax,height
mov x1,eax
sub ebx,height
mov y1,ebx
add eax,height
subeax,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
subeax,5
add ebx,height
mov x5,eax
mov y5,ebx
pop edx
popecx
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:='The Spring of Storm...';
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,'Green ocean...rest time^_^!');
//DrawTree;
end;
procedure TForm1.Autumn1Click(Sender: TObject);
begin
drawClear;
form1.Canvas.Font.Color:=clblue;
form1.Canvas.Font.Size:=18;
form1.canvas.textOut(150,150,'Red leaves and fragrant mountains...are resting^_^!');
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,'Silver snake wax elephant...not open yet^_^!');
end;
procedure TForm1.ext1Click(Sender: TObject);
begin
form5.Show;
end;
end.
The following is the attached test program using floating point instructions. The original version at that time did not achieve the effect :):
//Instruct the library to check:)
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
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;
I chose one of the processes, haha, funny.
You might as well take out your stuff and share your experience, I’m ready to listen :).
please----