Subsections


3. Using Assembly language

Free Pascal supports inserting of assembler instructions in your code. The mechanism for this is the same as under Turbo Pascal. There are, however some substantial differences, as will be explained in the following.


3.1 Intel syntax

As of version 0.9.7, Free Pascal supports Intel syntax for the Intel family of Ix86 processors in it's asm blocks.

The Intel syntax in your asm block is converted to AT&T syntax by the compiler, after which it is inserted in the compiled source. The supported assembler constructs are a subset of the normal assembly syntax. In what follows we specify what constructs are not supported in Free Pascal, but which exist in Turbo Pascal:

The Intel inline assembler supports the following macros :

@Result
represents the function result return value.
Self
represents the object method pointer in methods.


3.2 AT&T Syntax

Free Pascal uses the GNU as assembler to generate its object files for the Intel Ix86 processors . Since the GNU assembler uses AT&T assembly syntax, the code you write should use the same syntax. The differences between AT&T and Intel syntax as used in Turbo Pascal are summarized in the following:

More information about the AT&T syntax can be found in the as manual, although the following differences with normal AT&T assembly must be taken into account :

The AT&T inline assembler supports the following macros :

__RESULT
represents the function result return value.
__SELF
represents the object method pointer in methods.
__OLDEBP
represents the old base pointer in recusrive routines.


3.3 Calling mechanism

Procedures and Functions are called with their parameters on the stack. Contrary to Turbo Pascal, all parameters are pushed on the stack, and they are pushed right to left, instead of left to right for Turbo Pascal. This is especially important if you have some assembly subroutines in Turbo Pascal which you would like to translate to Free Pascal.

Function results are returned in the accumulator, if they fit in the register.

The registers are not saved when calling a function or procedure. If you want to call a procedure or function from assembly language, you must save any registers you wish to preserve.

When you call an object method from assembler, you must load the ESI register with the self pointer of the object or class.

The first thing a procedure does is saving the base pointer, and setting the base pointer equal to the stack pointer. References to the pushed parameters and local variables are constructed using the base pointer.

When the procedure or function exits, it clears the stack.

When you want your code to be called by a C library or used in a C program, you will run into trouble because of this calling mechanism. In C, the calling procedure is expected to clear the stack, not the called procedure. In other words, the arguments still are on the stack when the procedure exits. To avoid this problem, Free Pascal supports the export modifier. Procedures that are defined using the export modifier, use a C-compatible calling mechanism. This means that they can be called from a C program or library, or that you can use them as a callback function.

This also means that you cannot call this procedure or function from your own program, since your program uses the Pascal calling convention. However, in the exported function, you can of course call other Pascal routines.

As of version 0.9.8, the Free Pascal compiler supports also the cdecl and stdcall modifiers, as found in Delphi. The cdecl modifier does the same as the export modifier, and stdcall does nothing, since Free Pascal pushes the paramaters from right to left by default. In addition to the Delphi cdecl construct, Free Pascal also supports the popstack directive; it is nearly the same a the cdecl directive, only it still mangles the name, i.e. makes it into a name such as the compiler uses internally.

All this is summarized in table (Calling) . The first column lists the modifier you specify for a procedure declaration. The second one lists the order the paramaters are pushed on the stack. The third column specifies who is responsible for cleaning the stack: the caller or the called function. Finally, the last column specifies if registers are used to pass parameters to the function.


Table: Calling mechanisms in Free Pascal
Modifier Pushing order Stack cleaned by Parameters in registers
(none) Right-to-left Function No
cdecl Right-to-left Caller No
export Right-to-left Caller No
stdcall Right-to-left Function No
popstack Right-to-left Caller No

More about this can be found in chapter Linking on linking.

3.3.1 Ix86 calling conventions

Standard entry code for procedures and functions is as follows on the x86 architecture:
   pushl   %ebp
   movl    %esp,%ebp

The generated exit sequence for procedure and functions looks as follows:

  leave
  ret  $xx

Where xx is the total size of the pushed parameters.

To have more information on function return values take a look at section RegConvs.

3.3.2 M680x0 calling conventions

Standard entry code for procedures and functions is as follows on the 680x0 architecture:

   move.l  a6,-(sp)
   move.l  sp,a6

The generated exit sequence for procedure and functions looks as follows:

  unlk   a6
  move.l (sp)+,a0     ; Get return address
  add.l  #xx,sp       ; Remove allocated stack
  move.l a0,-(sp)     ; Put back return address on top of the stack

Where xx is the total size of the pushed parameters.

To have more information on function return values take a look at section RegConvs.


3.4 Signalling changed registers

When the compiler uses variables, it sometimes stores them, or the result of some calculations, in the processor registers. If you insert assembler code in your program that modifies the processor registers, then this may interfere with the compiler's idea about the registers. To avoid this problem, Free Pascal allows you to tell the compiler which registers have changed. The compiler will then avoid using these registers. Telling the compiler which registers have changed, is done by specifying a set of register names behind an assembly block, as follows:
asm
  ...
end ['R1',...,'Rn'];
Here R1 to Rn are the names of the 32-bit registers you modify in your assembly code.

As an example :

   asm
   movl BP,%eax
   movl 4(%eax),%eax
   movl %eax,__RESULT
   end ['EAX'];
This example tells the compiler that the EAX register was modified.


3.5 Register Conventions

The compiler has different register conventions, depending on the target processor used.

3.5.1 Intel x86 version

When optimizations are on, no register can be freely modified, without first being saved and then restored. Otherwise, EDI is usually used as a scratch register and can be freely used in assembler blocks.

3.5.2 Motorola 680x0 version

Registers which can be freely modified without saving are registers D0, D1, D6, A0, A1, and floating point registers FP2 to FP7. All other registers are to be considered reserved and should be saved and then restored when used in assembler blocks.



root
2000-12-20