3.1.8.5. Inline Assembler¶
In C / C ++, specific assembler code described in the source program can be embedded in the output code of the compiler by using the asm statement.
3.1.8.5.1. Notes¶
Note the following when using the inline assembler (asm statement).
There are two types of asm statements (inline assembler): general format and GNU extension format. The general format is the format defined by the JIS C language standard “The asm keyword” and the C ++ language standard “asm declaration”.
Assemble files generated by the compiler are assembled by GNU assembler. Refer to the GNU assembler manual for the syntax format and available pseudo-instructions.
The compiler does not check the contents of the asm statement for correctness. It is necessary for the user to check for errors in the following items.
Instruction mnemonic spelling
Restriction of registers that can be used in instructions and specification of memory addresses
Correspondence of pseudo-instructions usually used in pairs
Duplicate symbols such as label names
ABI compliance (register save / restore, stack use conventions, etc.)
Delay slots after instructions that change the flow of control (call instructions, ret instructions, branch instructions, etc.) must be explicitly filled in by other instructions.
3.1.8.5.2. Compile¶
[_LNlogin]$ fccpx sample_asm.c (C) [_LNlogin]$ FCCpx sample_asm.cc (C++)
The C / C ++ compiler can output assembler code with the -S
option.
[_LNlogin]$ fccpx -S sample_asm.c (C) [_LNlogin]$ FCCpx -S sample_asm.cc (C++)
Attention
The C / C ++ compiler does not check the consistency between assembler instructions in asm statements and assembler instructions output by the compiler. The asm statement must be used at the user’s own risk.
3.1.8.5.3. asm statement (General format)¶
In C / C ++, any assembler instruction can be output to the assembler code output by the compiler by using the asm statement. In the general form, assembler instructions specified in the asm statement are passed to the assembler commands as is without any processing.
asm("Assembler instructions");
3.1.8.5.4. asm statement (GNU expanded format)¶
asm("Assembly template" : Output operand : Input operand : Destroy register );
asm can be described as __asm__ .
__asm__("Assembly template" : Output operand : Input operand : Destroy register );
Each register description is described as character string data, and the same register description as the following register table is described.
For the output operand and the input operand, describe one operand description or two or more operand descriptions connected with commas (“,”).
Operands are numbered starting from 0 (up to 10) through output and input operands. The number is used in the assembler instruction description to specify the position of the operand in the form of “% n” (where n is the number of a single-digit operand).
For an assembler instruction that does not have an output operand, write two colons (“:”) between the description of the assembler instruction and the description of the input operand.
To write a multi-line asm statement at a time in an assembly template, insert a line feed character (\ n) and a tab character (\ t).
3.1.8.5.5. I/O operand¶
The output operand / input operand consists of a symbol operand name, an operand constraint string, and an operand.
[ Symbol operand name ] "Operand constraint string" (Operand)
In the description of assembler instructions, there is a method of using a symbol operand to specify the position of the operand. Symbol operand names are required only when using symbol operands in assembler instructions. The notation in assembler instructions is `%’`[‘symbol operand name`]’.
Write a C / C ++ expression in the operand part of ().
The symbol operand name has no relation to the identifier name in the C / C ++ program outside the asm statement, and even if the same variable name is already used, it is not considered to refer to the same entity.
It is the user’s responsibility to ensure that the type of the input operand expression is appropriate as the type required for the operands of the assembler instruction.
3.1.8.5.6. Constraint character¶
The following table shows the restriction characters accepted by the C / C ++ compiler.
Constraint character
Description
X
Indicates any operand.
g
Indicates any general-purpose register, memory, or constant.
0,1,2,3,4,5,6,7,8,9
Indicates the same operand as the one already specified, with the same number as the number.
[
Indicates symbol operand name starts.
r
Indicates general purposeregister.
f
Indicates the lower 32 bits of the floating-point register.
m
Indicates memory.
p
Indicates available memory address.It is used load address direction and push address direction.o
Indicates memory that is as off-set table.
V
Indicates memory that is not off-set table.
i
Indicates an integer constant. The constant value must be fixed at the time of assembly.
s
Indicates an integer constant that is unknown at compile time.
E
Indicates a floating point constant.It can be used when the floating point format of the target machine and the machine running the compiler match.F
Indicates a floating point constant.
J
Indicates zero.
Additional information can be specified before the constraint character. If there is no additional information, the constraint character is interpreted as an input-only operand.
Attached information
Description
=
Means output only operand.
+
Means updated operand (Input and output is both proceeded).
&
Used as an input operand, but it means that the operand is updated before the instruction group finishes.
3.1.8.5.7. How to specify names in assembler code¶
If you want to use different names for variables and functions on the C / C ++ source when outputting to assembler, write the asm description immediately after the declarator. #pragma redefine_extname
direction is the same meaning with the description method.
int foo asm("myfoo") = 2;
3.1.8.5.8. How to specify the specific register¶
To assign the variable of C/C++ source to the specific hardware register, when defining the variable, specify “register” of the memory area class.
register int foo asm("g2");Attention
The name specified in the asm description cannot be the same as the register names shown in the following table.
Names specified as assembler instructions, pseudo-instructions, or special register names in the assembler specifications cannot be specified.
3.1.8.5.9. Specification example (GNU expanded format)¶
This indicates the Specification example of GNU expanded format.
- Example 1 (Input/Output operand)Here is an example of an assembler instruction with input and output operands.
int asm_in1=5, asm_in2=10; int asm_out1, asm_out2; asm ( "asm_op %0,%2\n\tasm_op %1,%3" // assembler template : "=r" (asm_out1) , "=r" (asm_out2) // output operands : "r" (asm_in1) , "r" (asm_in2) // input operandsOperands are numbered starting from 0 (up to 10) through output and input operands. The number is used in the assembler instruction description to specify the position of the operand in the form of “% n” (where n is the number of a single-digit operand).
Input operand “r” (asm_in1) → %0
Input operand “r” (asm_in2) → %1
Output operand “=r” (asm_out1) → %2
Output operand “=r” (asm_out2) → %3
- Example 2 (No Output operand)In the case of an assembler instruction that has no output operand, two colons (“:”) will be placed consecutively between the description of the assembler instruction and the input operand description.
int asm_in1=5, asm_in2=10; asm ( "asm_op %0\t\nasm_op %1" // assembler template : // output operands : "r" (asm_in1) , "r" (asm_in2) // input operands
- Example 3 (volatile)By writing volatile immediately after asm, you can instruct the C / C ++ compiler that assembler instructions have serious side effects.
int asm_out; asm volatile ("asm_op %0" : "=r" (asm_out) );