Using inline Assembly

You can use inline assembly language in your source code in twoways:

Using the ASM statement, which can be placed anywhere a statementis allowed

Using assembler procedures, which are entire procedures thatare implemented in assembly language.

The documentation for the compiler built-in assembler assumesyou are familiar with assembly code and have written some assembly code before.

The ASM statement

The syntax of the ASM statement is:

ASM {AssemblerStatement}END

This statement can be used anywhere a statement is allowed ina Modula-2 program.

Note: Usage of the ASM statement should be avoided innormal procedures, since it reduces the code optimizations the compiler can perform.

EXAMPLE: Using the ASM statement

This example multiplies two integers, X and Y, and places theirlongint product in L:

ASM
   MOV AX, X
   IMUL Y
   MOV WORD PTR L, AX
   MOV WORD PTR L+2, DX
END;

ASSEMBLER procedures

Assembler procedures are procedures implemented entirely in assemblycode. This is the preferred mechanism to use assembly code.

The syntax of a Modula-2 assembler procedure is:

PROCEDURE ProcedureIdentifier [FormalParameterPart ]; ASSEMBLER;
{Declarations }
AsmStatement;

The syntax of an Ada95 assembler procedure is:

Procedure ProcedureIdentifier [FormalParameterPart ] is

Pragma Assembler;
{Declarations }
AsmStatement;

 

Function ProcedureIdentifier [FormalParameterPart ] is

Pragma Assembler;
{Declarations }
AsmStatement;

Implementing a procedure in assembly language has some effecton how the compiler translates the procedure:

32-bit IA-32 compilers:

SPARC compilers

16-bit IA-32 compilers:

Modula-2 32-bit example

PROCEDURE Div(dividend : LONGINT; divisor : INTEGER) : INTEGER; ASSEMBLER;

ASM

mov eax, dword ptr dividend

mov edx, dword ptr dividend + 4

idiv divisor

END Div;

Ada95 32-bit example

Procedure Div(dividend : Long_Integer; divisor : Integer) returnInteger is

Pragma Assembler;

ASM

mov eax, dword ptr dividend

mov edx, dword ptr dividend + 4

idiv divisor

END Div;

PUREASM Procedures

PureAsm procedures are a variant of Assembler procedures.  Witha PureAsm procedure the compiler does not allocate a stack frame or put space onthe stack for local variables (as it does with normal Assembler procedures).  Itis up to you to create the stack frame and local space for variables.

EXAMPLE: Using the PureAsm assembler procedure

Normal Assembler procedure version:

PROCEDURE MyProc(w : INTEGER; x : INTEGER) : INTEGER; ASSEMBLER;
VAR
   temp : INTEGER;
ASM
   MOV EAX, 10
   MUL w
   MOV temp, EAX
   MOV EAX, 99
   MUL x
   ADD EAX, temp
END MyProc;

PureAsm version:

PROCEDURE MyProc(w : INTEGER; x : INTEGER) : INTEGER; PUREASM;
VAR
   temp : INTEGER;
ASM
   PUSH EBP
   MOV EBP, ESP
   SUB ESP, 4
   MOV EAX, 10
   MUL w
   MOV temp, EAX
   MOV EAX, 99
   MUL x
   ADD EAX, temp
   MOV ESP, EBP
   POP EBP
   RET 4
END MyProc;

Notice, the PureAsm version created a stack frame and created4 bytes of temp variable space on entry.  Additionally, the PureAsm procedureremoved the stack frame and returned on exit.  In other words the PureAsm procedureis exactly that, a procedure which is assembler, allowing symbolic references tovariables (constants...), but the compiler does not create any "unseen"helper instructions for the programmer.

Note Modula-2 only: For both Assembler and PureAsm procedures,the compiler can assign symbolic names to local variables placed in registers. Thefollowing syntax is used in the declaration:

symbolName [REGISTER RegisterName] : Type;

Example:

localVarible [REGISTER CX] : INTEGER;

Note IA-32: The register specified must be AX, BX, CX,DX, SI, or DI.  The data type size controls if the byte, word, or dword registeris used.  For example, if AX is the specified register the data type size woulddetermine if AL, AX, or EAX is actually used.