Difference between revisions of "Lazarus Inline Assembler/es"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(15 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{Lazarus Inline Assembler}}
 
{{Lazarus Inline Assembler}}
  
Esto es un esbozo para alentar a otros a contribuir con más información. A continuación un ejemplo sencillo como punto de partida:
+
   Esto es un esbozo para alentar a otros a contribuir con más información. A continuación un ejemplo sencillo como punto de partida [http://wiki.freepascal.org/Lazarus_Inline_Assembler Lazarus_Inline_Assembler]:
<syntaxhighlight>
+
 
unit unit_asm;
+
<syntaxhighlight lang=pascal>
{$mode objfpc}{$H+}
+
unit unit_asm;
interface
+
{$mode objfpc}{$H+}
uses
+
interface
 +
uses
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
+
type
 
   { TForm1 }
 
   { TForm1 }
 
   TForm1 = class(TForm)
 
   TForm1 = class(TForm)
Line 22: Line 23:
 
     { public declarations }
 
     { public declarations }
 
   end;  
 
   end;  
var
+
var
 
   Form1: TForm1;  
 
   Form1: TForm1;  
implementation
+
implementation
{ TForm1 }
+
{ TForm1 }
  
procedure TForm1.btnGoClick(Sender: TObject);
+
procedure TForm1.btnGoClick(Sender: TObject);
var
+
var
   num, answer : integer;
+
   num, answer : integer; {define dos variables de tipo entero: num (número) y answer (respuesta) }
begin
+
begin
   num := StrToInt(edtInput.Text);
+
   num := StrToInt(edtInput.Text); { Convierte la cadena a entero y se lo asigna a la variable num }
 
   // Se requiere esto con Lazarus en x86, definimos el modo ensamblador de Intel:
 
   // Se requiere esto con Lazarus en x86, definimos el modo ensamblador de Intel:
 
   {$ASMMODE intel}
 
   {$ASMMODE intel}
 
   asm
 
   asm
 
     MOV EAX, num
 
     MOV EAX, num
     ADD EAX, 110B //add binary 110
+
     ADD EAX, 110B //sumar el numero 110 binario (6 en decimal) al contenido del registro EAX.
     SUB EAX, 2    //subtract decimal 2
+
     SUB EAX, 2    //restar o substraer el número 2 decimal (no lleva la B de binario) al contenido del registro EAX.
     MOV answer, EAX
+
     MOV answer, EAX //mover el contenido de EAX a la variable answer.
 
   end;
 
   end;
   edtOutput.Text := IntToStr(answer);
+
   edtOutput.Text := IntToStr(answer); { Convierte el número entero a su equivalente en cadena & pasa a la propiedad texto }
end;
+
end;
  
initialization
+
initialization
 
   {$I unit_asm.lrs}
 
   {$I unit_asm.lrs}
end.</syntaxhighlight>
+
end.</syntaxhighlight>
 +
 
 +
&nbsp;&nbsp;&nbsp;En el siguiente enlace podéis encontrar una muy buena descripción al respecto en la documentación de FreePascal:
 +
 
 +
*[http://www.freepascal.org/docs-html/prog/progse9.html Utilizando lenguaje ensamblador en el codigo fuente], está en inglés así que lo pongo aquí traducido, añadiendo también este enlace [http://www.freepascal.org/docs-html/prog/progsu3.html a directivas para ensamblador] y su respectiva traducción:
  
En el siguiente enlace podéis encontrar una muy buena descripción al respecto en la documentación de FreePascal:
+
  $ASMMODE : Modo ensamblador (Intel 80x86 solamente)
  
[http://www.freepascal.org/docs-html/prog/progse9.html Utilizando lenguaje ensamblador en el codigo fuente], está en inglés así que lo pongo aquí traducido, añadiendo tambien este enlace [http://www.freepascal.org/docs-html/prog/progsu3.html a directivas para ensamblador] y su respectiva traducción:
+
&nbsp;&nbsp;&nbsp;La directiva {$ASMMODE XXX} informa al compilador sobre el tipo de ensamblador que debe esperar en el/los bloques escritos en ensamblador. Aquí XXX debería reemplazarse por alguno de los siguientes valores:
  
1.2.3 $ASMMODE : Assembler mode (Intel 80x86 only)
+
*'''att:''' Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de AT&T.  
  
The {$ASMMODE XXX} directive informs the compiler what kind of assembler it can expect in an asm block. The XXX should be replaced by one of the following:
+
*'''intel:''' Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de Intel.  
  
att
+
*'''direct:''' Indica al compilador que los bloques asm deben ser copiados directamente al fichero en ensamblador. No es posible utilizar estos bloques en ensamblador cuando se está utilizando un ensamblador interno por parte del compilador.
    Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de AT&T.
 
intel
 
    Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de Intel.
 
direct  
 
    Indica al compilador que los bloques asm deben ser copiados directamente al fichero en ensamblador. No es posible utilizar estos bloques en ensamblador cuando se está utilizando un ensamblador interno por parte del compilador.
 
  
Estas opciones son locales y retienen su valor hasta el final de la unidad que es compilada, al menos que sean reemplazados utilizando
+
&nbsp;&nbsp;&nbsp;Estas opciones son locales y retienen su valor hasta el final de la unidad que es compilada, al menos que sean reemplazados utilizando alguna otra directiva del mismo tipo. La opción a nivel de línea de mandatos que corresponde a esto es -R.
alguna otra directiva del mismo tipo. La opción a nivel de línea de mandatos que corresponde a esto es -R.
 
These switches are local, and retain their value to the end of the unit that is compiled, unless
 
  
they are replaced by another directive of the same type. The command line switch that corresponds to this switch is -R.
+
&nbsp;&nbsp;&nbsp;En el IDE de Lazarus podemos encontrar estas opciones para el proyecto en curso:
  
El lector de ensamblador que se utiliza por defecto si no se especifica otro es AT&T.
+
&nbsp;&nbsp;&nbsp;El interprete de ensamblador predeterminado, si no se especifica otro, es AT&T.
  
Hay esencialmente 2 modos de embeber código ensamblador en código fuente pascal. La primera es la más simple y consiste
+
&nbsp;&nbsp;&nbsp;Hay esencialmente 2 modos de embeber código ensamblador en código fuente pascal. La primera es la más simple y consiste en utilizar un bloque asm:
en utilizar un bloque asm:
 
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
Var  
+
var  
 
   I : Integer;   
 
   I : Integer;   
begin   
+
begin   
 
   I:=3;   
 
   I:=3;   
 
   asm   
 
   asm   
 
   movl I,%eax   
 
   movl I,%eax   
 
   end;   
 
   end;   
end;
+
end;</syntaxhighlight>
</syntaxhighlight>
 
  
Todo lo que está contenido entre 'asm' y 'end' define un bloque que se inserta como código ensamblador en el código generado. Dependiendo del modo del lector ensamblador, el compilador realizará la sustitución de ciertos nombres por sus
+
&nbsp;&nbsp;&nbsp;Todo lo que está contenido entre 'asm' y 'end' define un bloque que se inserta como código ensamblador en el código generado. Dependiendo del modo del interprete ensamblador, el compilador realizará la sustitución de ciertos nombres por sus direcciones.  
direccciones.  
 
  
El segundo modo es implementando una función o bien un procedimiento completamente en ensamblador. Esto se realiza añadiendo un modificador a la cabecera de la función o procedimiento:
+
&nbsp;&nbsp;&nbsp;El segundo modo es implementando una función o bien un procedimiento completamente en ensamblador. Esto se realiza añadiendo el modificador '''assembler''' a la cabecera de la función o procedimiento :
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
{$ASMMODE att} / pero recordar que es el que utiliza por defecto si no se especifica otro
+
{$ASMMODE att} // pero recordar que es el que utiliza por defecto si no se especifica otro
function geteipasebx : pointer;assembler;   
+
function geteipasebx : pointer;assembler;   
asm   
+
asm   
 
   movl (%esp),%ebx   
 
   movl (%esp),%ebx   
 
   ret   
 
   ret   
end;
+
end;</syntaxhighlight>
</syntaxhighlight>
 
  
Es posible todavía declarar variables para el procedimiento en ensamblador:
+
&nbsp;&nbsp;&nbsp;Es posible todavía declarar variables para el procedimiento en ensamblador:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
procedure Move(const source;var dest;count:SizeInt);assembler;   
+
procedure Move(const source;var dest;count:SizeInt);assembler;   
var   
+
var   
 
   saveesi,saveedi : longint;   
 
   saveesi,saveedi : longint;   
asm   
+
asm   
 
   movl %edi,saveedi   
 
   movl %edi,saveedi   
end;
+
end;</syntaxhighlight>
</syntaxhighlight>
 
  
El compilador reservará espacio en la pila para estas variables, esto inserta algunos comandos para ello.
+
&nbsp;&nbsp;&nbsp;El compilador reservará espacio en la pila para estas variables, esto inserta algunos comandos para ello.
  
Tener en cuenta que el nombre ensamblador de una función en ensamblador todavía puede ser 'mangled' por el compilador. Por ejemplo la etiqueta para esta función no deberá ser el nombre de la función declarada. Para cambiar esto se puede utilizar un modificador Alias:
+
&nbsp;&nbsp;&nbsp;Debemos tener en cuenta que el nombre ensamblador de una función en ensamblador todavía puede ser 'mangled' por el compilador. Por ejemplo la etiqueta para esta función no deberá ser el nombre de la función declarada. Para cambiar esto se puede utilizar un modificador Alias:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>  
 
function geteipasebx : pointer;assembler;[alias:’FPC_GETEIPINEBX’];   
 
function geteipasebx : pointer;assembler;[alias:’FPC_GETEIPINEBX’];   
asm   
+
asm   
 
   movl (%esp),%ebx   
 
   movl (%esp),%ebx   
 
   ret   
 
   ret   
end;
+
end;</syntaxhighlight>
</syntaxhighlight>
 
  
Para hacer que la función esté disponible en código ensamblador fuera de la actual unit se debe añadir el modificador 'public':
+
&nbsp;&nbsp;&nbsp;Para hacer que la función esté disponible en código ensamblador fuera de la unidad actual debemos añadir el modificador '''public''':
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>  
 
function geteipasebx : pointer;assembler;[public,alias:’FPC_GETEIPINEBX’];   
 
function geteipasebx : pointer;assembler;[public,alias:’FPC_GETEIPINEBX’];   
asm   
+
asm   
 
   movl (%esp),%ebx   
 
   movl (%esp),%ebx   
 
   ret   
 
   ret   
end;  
+
end;</syntaxhighlight>
</syntaxhighlight>
 
 
 
[[Category:Tutorials]]
 

Latest revision as of 01:16, 19 February 2020

English (en) español (es) français (fr) 日本語 (ja) 한국어 (ko) русский (ru) Tiếng Việt (vi)

   Esto es un esbozo para alentar a otros a contribuir con más información. A continuación un ejemplo sencillo como punto de partida Lazarus_Inline_Assembler:

 unit unit_asm;
 {$mode objfpc}{$H+}
 interface
 uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
 type
  { TForm1 }
  TForm1 = class(TForm)
    btnGo: TButton;
    edtInput: TEdit;
    edtOutput: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure btnGoClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 
 var
  Form1: TForm1; 
 implementation
 { TForm1 }

 procedure TForm1.btnGoClick(Sender: TObject);
 var
  num, answer : integer; {define dos variables de tipo entero: num (número) y answer (respuesta) }
 begin
  num := StrToInt(edtInput.Text); { Convierte la cadena a entero y se lo asigna a la variable num }
  // Se requiere esto con Lazarus en x86, definimos el modo ensamblador de Intel:
  {$ASMMODE intel}
  asm
    MOV EAX, num
    ADD EAX, 110B //sumar el numero 110 binario (6 en decimal) al contenido del registro EAX. 
    SUB EAX, 2    //restar o substraer el número 2 decimal  (no lleva la B de binario) al contenido del registro EAX.
    MOV answer, EAX //mover el contenido de EAX a la variable answer.
  end;
  edtOutput.Text := IntToStr(answer); { Convierte el número entero a su equivalente en cadena & pasa a la propiedad texto }
 end;

 initialization
  {$I unit_asm.lrs}
 end.

   En el siguiente enlace podéis encontrar una muy buena descripción al respecto en la documentación de FreePascal:

 $ASMMODE : Modo ensamblador (Intel 80x86 solamente)

   La directiva {$ASMMODE XXX} informa al compilador sobre el tipo de ensamblador que debe esperar en el/los bloques escritos en ensamblador. Aquí XXX debería reemplazarse por alguno de los siguientes valores:

  • att: Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de AT&T.
  • intel: Indica que los bloques asm contienen sintaxis en la modalidad ensamblador de Intel.
  • direct: Indica al compilador que los bloques asm deben ser copiados directamente al fichero en ensamblador. No es posible utilizar estos bloques en ensamblador cuando se está utilizando un ensamblador interno por parte del compilador.

   Estas opciones son locales y retienen su valor hasta el final de la unidad que es compilada, al menos que sean reemplazados utilizando alguna otra directiva del mismo tipo. La opción a nivel de línea de mandatos que corresponde a esto es -R.

   En el IDE de Lazarus podemos encontrar estas opciones para el proyecto en curso:

   El interprete de ensamblador predeterminado, si no se especifica otro, es AT&T.

   Hay esencialmente 2 modos de embeber código ensamblador en código fuente pascal. La primera es la más simple y consiste en utilizar un bloque asm:

 var  
  I : Integer;  
 begin  
  I:=3;  
  asm  
   movl I,%eax  
  end;  
 end;

   Todo lo que está contenido entre 'asm' y 'end' define un bloque que se inserta como código ensamblador en el código generado. Dependiendo del modo del interprete ensamblador, el compilador realizará la sustitución de ciertos nombres por sus direcciones.

   El segundo modo es implementando una función o bien un procedimiento completamente en ensamblador. Esto se realiza añadiendo el modificador assembler a la cabecera de la función o procedimiento :

 {$ASMMODE att} // pero recordar que es el que utiliza por defecto si no se especifica otro
 function geteipasebx : pointer;assembler;  
 asm  
  movl (%esp),%ebx  
  ret  
 end;

   Es posible todavía declarar variables para el procedimiento en ensamblador:

 procedure Move(const source;var dest;count:SizeInt);assembler;  
 var  
  saveesi,saveedi : longint;  
 asm  
  movl %edi,saveedi  
 end;

   El compilador reservará espacio en la pila para estas variables, esto inserta algunos comandos para ello.

   Debemos tener en cuenta que el nombre ensamblador de una función en ensamblador todavía puede ser 'mangled' por el compilador. Por ejemplo la etiqueta para esta función no deberá ser el nombre de la función declarada. Para cambiar esto se puede utilizar un modificador Alias:

 
function geteipasebx : pointer;assembler;[alias:FPC_GETEIPINEBX];  
 asm  
  movl (%esp),%ebx  
  ret  
 end;

   Para hacer que la función esté disponible en código ensamblador fuera de la unidad actual debemos añadir el modificador public:

 
function geteipasebx : pointer;assembler;[public,alias:FPC_GETEIPINEBX];  
 asm  
  movl (%esp),%ebx  
  ret  
 end;