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.