3.1 Using assembler in the sources

There are essentially 2 ways to embed assembly code in the pascal source. The first one is the simplest, by using an asm block:

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

Everything between the asm and end block is inserted as assembler in the generated code. Depending on the assembler reader mode, the compiler performs substitution of certain names with their addresses.

The second way is implementing a complete procedure or function in assembler. This is done by adding a assembler modifier to the function or procedure header:

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

It’s still possible to declare variables in an assembler procedure:

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

The compiler will reserve space on the stack for these variables, it inserts some commands for this.

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. To change this, an Alias modifier can be used:

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

To make the function available in assembler code outside the current unit, the Public modifier can be added:

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