Using Inline Assembly Code

From RAD Studio
Jump to: navigation, search

Go Up to Inline Assembly Code Index


The built-in assembler allows you to write assembly code within Delphi programs. It has the following features:

  • Allows for inline assembly.
  • Supports all instructions found in the Intel Pentium 4, Intel MMX extensions, Streaming SIMD Extensions (SSE), and the AMD Athlon (including 3D Now!).
  • Supports the Intel 64 architecture, with some limitations.
  • Permits the use of Delphi identifiers, such as constants, types, and variables in assembly statements.
  • Provides no macro support, but allows for pure assembly function procedures.

As an alternative to the built-in assembler, you can link to object files that contain external procedures and functions. See the topic External Declarations for more information. If you have external assembly code that you want to use in your applications, you should consider rewriting it in the Delphi language or minimally reimplement it using the inline assembler.

The inline assembler is available on:

However, inline assembly is not supported by the Delphi compilers for the iOS device and Android device.

Using the asm Statement

The built-in assembler is accessed through asm statements, which have the form:

asm statementList end

where statementList is a sequence of assembly statements separated by semicolons, end-of-line characters, or Delphi comments.

Comments in an asm statement must be in Delphi style. A semicolon does not indicate that the rest of the line is a comment.

The reserved word inline and the directive assembler are maintained for backward compatibility only. They have no effect on the compiler.

Using Registers

X64 GPR.pngX64 SSE.png

32-bit

In general, the rules of register use in an asm statement are the same as those of an external procedure or function. An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers, but can freely modify the EAX, ECX, and EDX registers. On entry to an asm statement, EBP points to the current stack frame and ESP points to the top of the stack. Except for ESP and EBP, an asm statement can assume nothing about register contents on entry to the statement.

64-bit

In line with the x64 Application Binary Interface (ABI), the contents of the following registers must be preserved and restored within inline assembly functions: R12, R13, R14, R15, RDI, RSI, RBX, RBP, RSP, XMM4, XMM5, XMM6, XMM7, XMM8, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, and XMM15.

The first four parameters to inline assembler functions are passed via RCX, RDX, R8, and R9 respectively, except for floating-point arguments which use XMMO, XMM1, XMM2, XMM3. The math coprocessor is not normally used from x64 code. Registers used for function parameters can be modified freely.

Using Conditional Defines for Cross-Platform Code

For existing functions with inline Assembly code, conditional defines must be used to differentiate between platforms. Functions should have a common function prototype between platforms. Example:

function Power10(val: Extended; power: Integer): Extended; 
{$IFDEF PUREPASCAL}
begin
  // Pascal implementation here...
end;
{$ELSE !PUREPASCAL}
{$IFDEF CPUX86}
  asm
    // ASM implementation here...
  end;
{$ENDIF CPUX86}
{$ENDIF !PUREPASCAL}

Example without $ELSE:

  {$IFDEF CPUX86}
  asm
    // ...
  end;
  {$ENDIF CPUX86}
  {$IFDEF CPUX64}
  asm
    // ...
  end;
{$ENDIF CPUX64}

For more information about the predefined conditionals, see Conditional compilation. Predefined Conditionals.

See Also