Assembly Procedures and Functions

From RAD Studio
Jump to: navigation, search

Go Up to Inline Assembly Code Index

You can write complete procedures and functions using inline assembly language code, without including a begin...end statement.

Compiler Optimizations

An example of the type of function you can write is as follows:

function LongMul(X, Y: Integer): Longint;
asm
  MOV  EAX,X
  IMUL    Y
end;

The compiler performs several optimizations on these routines:

  • No code is generated to copy value parameters into local variables. This affects all string-type value parameters and other value parameters whose size isn't 1, 2, or 4 bytes. Within the routine, such parameters must be treated as if they were var parameters.
  • Unless a function returns a string, variant, or interface reference, the compiler doesn't allocate a function result variable; a reference to the @Result symbol is an error. For strings, variants, and interfaces, the caller always allocates an @Result pointer.
  • The compiler only generates stack frames for nested routines, for routines that have local parameters, or for routines that have parameters on the stack.
  • Locals is the size of the local variables and Params is the size of the parameters. If both Locals and Params are zero, there is no entry code, and the exit code consists simply of a RET instruction.

The automatically generated entry and exit code for the routine looks like this:

PUSH   EBP         ;Present if Locals <> 0 or Params <> 0
MOV    EBP,ESP         ;Present if Locals <> 0 or Params <> 0
SUB    ESP,Locals      ;Present if Locals <> 0
; …
MOV    ESP,EBP         ;Present if Locals <> 0
POP    EBP         ;Present if Locals <> 0 or Params <> 0
RET    Params          ;Always present

If locals include variants, long strings, or interfaces, they are initialized to zero but not finalized.

Function Results

Assembly language functions return their results as follows.

32-bit

  • Ordinal values are returned in AL (8-bit values), AX (16-bit values), or EAX (32-bit values).
  • Real values are returned in ST(0) on the coprocessor's register stack. (Currency values are scaled by 10000.)
  • Pointers, including long strings, are returned in EAX.
  • Short strings and variants are returned in the temporary location pointed to by @Result.


64-bit

  • Values 8 bytes or less in size are return in RAX.
  • Real values are returned in XMM0.
  • Other types are returned by a reference whose pointer value resides in RAX whose memory is allocated by the calling routine.

Intel 64 Specifics (Pseudo-Ops)

x64 functions must be written completely in assembly or Pascal, that is, assembler statements are not supported, only inline assembly functions.

Pseudo-ops have been provided to help manage stack use in x64: .PARAMS, .PUSHNV, .SAVENV and .NOFRAME.

Pseudo-op

Description

.PARAMS <number>

Used when calling external functions to setup the register parameter backing store as per the x64 calling convention as this is not normally done by default. When used, a pseudo-variable, @params, is available for passing stack params to called functions. Use @params as a byte array where the first stack parameter will be @params[32], locations 0-31 represent the 4 register parameters.

.PUSHNV <register>

Generates code to save and restore the non-volatile general purpose register in the prologue and epilogue.

.SAVENV <XMM register>

Same functionality as .PUSHNV for non-volatile XMM registers.

.NOFRAME

Forcibly disables the generation of a stack frame as long as there are no local variables declared and the parameter count <= 4. Use only for leaf functions.

Stack Unwinding for PC-mapped Exceptions

See PC-Mapped Exceptions#Unwinding Assembly Routines.

See Also