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 Machine_Code_Insertions section of 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
-S
-fomit-frame-pointer
-gnatp
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
.