Next: , Previous: Basic Assembler Syntax, Up: Inline Assembler


D.2 A Simple Example of Inline Assembler

The following example will generate a single assembly language statement, nop, which does nothing. Despite its lack of run-time effect, the example will be useful in illustrating the basics of the Inline Assembler facility.

     with System.Machine_Code; use System.Machine_Code;
     procedure Nothing is
     begin
        Asm ("nop");
     end Nothing;

Asm is a procedure declared in package System.Machine_Code; here it takes one parameter, a template string that must be a static expression and that will form the generated instruction. Asm may be regarded as a compile-time procedure that parses the template string and additional parameters (none here), from which it generates a sequence of assembly language instructions.

The examples in this chapter will illustrate several of the forms for invoking Asm; a complete specification of the syntax is found in the GNAT Reference Manual.

Under the standard GNAT conventions, the Nothing procedure should be in a file named nothing.adb. You can build the executable in the usual way:

     gnatmake nothing

However, the interesting aspect of this example is not its run-time behavior but rather the generated assembly code. To see this output, invoke the compiler as follows:

        gcc -c -S -fomit-frame-pointer -gnatp nothing.adb

where the options are:

-c
compile only (no bind or link)
-S
generate assembler listing
-fomit-frame-pointer
do not set up separate stack frames
-gnatp
do not add runtime checks

This gives a human-readable assembler version of the code. The resulting file will have the same name as the Ada source file, but with a .s extension. In our example, the file nothing.s has the following contents:

     .file "nothing.adb"
     gcc2_compiled.:
     ___gnu_compiled_ada:
     .text
        .align 4
     .globl __ada_nothing
     __ada_nothing:
     #APP
        nop
     #NO_APP
        jmp L1
        .align 2,0x90
     L1:
        ret

The assembly code you included is clearly indicated by the compiler, between the #APP and #NO_APP delimiters. The character before the 'APP' and 'NOAPP' can differ on different targets. For example, GNU/Linux uses '#APP' while on NT you will see '/APP'.

If you make a mistake in your assembler code (such as using the wrong size modifier, or using a wrong operand for the instruction) GNAT will report this error in a temporary file, which will be deleted when the compilation is finished. Generating an assembler file will help in such cases, since you can assemble this file separately using the as assembler that comes with gcc.

Assembling the file using the command

     as nothing.s

will give you error messages whose lines correspond to the assembler input file, so you can easily find and correct any mistakes you made. If there are no errors, as will generate an object file nothing.out.