Difference between revisions of "Lazarus Inline Assembler/es"
Line 54: | Line 54: | ||
en utilizar un bloque asm: | en utilizar un bloque asm: | ||
+ | <syntaxhighlight> | ||
Var | Var | ||
I : Integer; | I : Integer; | ||
Line 62: | Line 63: | ||
end; | end; | ||
end; | end; | ||
+ | </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 | 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 | ||
Line 68: | Line 70: | ||
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: | 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: | ||
− | + | <syntaxhighlight> | |
function geteipasebx : pointer;assembler; | function geteipasebx : pointer;assembler; | ||
asm | asm | ||
Line 74: | Line 76: | ||
ret | ret | ||
end; | end; | ||
+ | </syntaxhighlight> | ||
Es posible todavía declarar variables para el procedimiento en ensamblador: | Es posible todavía declarar variables para el procedimiento en ensamblador: | ||
+ | <syntaxhighlight> | ||
procedure Move(const source;var dest;count:SizeInt);assembler; | procedure Move(const source;var dest;count:SizeInt);assembler; | ||
var | var | ||
Line 83: | Line 87: | ||
movl %edi,saveedi | movl %edi,saveedi | ||
end; | end; | ||
− | + | </syntaxhighlight> | |
El compilador reservará espacio en la pila para estas variables, esto inserta algunos comandos para ello: | El compilador reservará espacio en la pila para estas variables, esto inserta algunos comandos para ello: | ||
Revision as of 13:02, 25 June 2014
│
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:
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;
begin
num := StrToInt(edtInput.Text);
// Se requiere esto con Lazarus en x86, definimos el modo ensamblador de Intel:
{$ASMMODE intel}
asm
MOV EAX, num
ADD EAX, 110B //add binary 110
SUB EAX, 2 //subtract decimal 2
MOV answer, EAX
end;
edtOutput.Text := IntToStr(answer);
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:
Utilizando lenguaje ensamblador en el codigo fuente, está en inglés así que lo pongo aquí traducido:
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 lector ensamblador, el compilador realizará la sustitución de ciertos nombres por sus 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:
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:
Tener en cuenta que el nombre ensamblador de una función en ensamblador . 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:
Note that the assembler name of an assembler function will still be ’mangled’ by the compiler, i.e. the label for this function will not be the name of the function as declared.
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 actual unit se debe añadir el modificador 'public':
function geteipasebx : pointer;assembler;[public,alias:’FPC_GETEIPINEBX’];
asm
movl (%esp),%ebx ret
end;