Linux Kernel series-embedded compilation of asm _ volatile __and asm _ volatile _ in C Language _

Source: Internet
Author: User
Tags processing instruction

Linux Kernel series-embedded compilation of asm _ volatile __and asm _ volatile _ in C Language _

In Embedded Assembly, the C language expression can be specified as the operand of the assembly instruction, and you do not have to worry about how to read the value of the C language expression into which register, and how to write the calculation result back to the C variable, you only need to tell the program the ing between the C language expression and the assembly instruction operand, GCC will automatically Insert the code to complete the necessary operations.

1. Simple Embedded Assembly
Example:

_ Asm _ volatile _ ("hlt"); "_ asm _" indicates that the subsequent code is embedded assembly, "asm" is the alias of "_ asm. "_ Volatile _" indicates that the compiler should not optimize the code, and the subsequent commands will remain unchanged. "volatile" is its alias. The brackets contain Assembly commands.

2. Example of Embedded Assembly
To use embedded assembly, you must first compile the assembly instruction template, then associate the C language expression with the instruction operand, And tell GCC What restrictions are imposed on these operations. For example, in the following Assembly statement:


_ Asm _ violate _ ("movl % 1, % 0": "= r" (result): "m" (input ));


"Movl % 1, % 0" is the instruction template; "% 0" and "% 1" represent the instruction operands, which are called placeholders, embedded Assembly relies on them to correspond the C language expression to the instruction operand. The instruction template is enclosed in parentheses in C language expressions. In this example, there are only two: "result" and "input ", they correspond to the command operations "% 0" and "% 1" in the order they appear. Note the order: the first C expression corresponds to "% 0 "; the second expression corresponds to "% 1", and so on. There are at most 10 operands, respectively, with "% 0", "% 1 ".... "% 9" indicates. There is a string enclosed in quotation marks before each operand. The content of the string is a limitation or requirement on the operand. "Result" indicates that the restricted string is "= r", where "=" indicates that "result" is the output operand, "r" indicates that you need to associate "result" with a general register. First, read the value of the operand into the Register, and then use the corresponding register in the instruction, instead of the result itself, of course, after executing the command, you need to store the value in the Register into the variable "result". On the surface, it seems that the command directly performs operations on "result". In fact, GCC implements implicit processing, in this way, we can write less commands. "R" in front of "input" indicates that the expression needs to be put into a register first, and then use this register in the instruction for calculation.
The relationship between a C expression or variable and a register is automatically handled by GCC. We only need to use a restricted string to guide GCC in how to handle it. The limit character must match the instruction's requirements on the operand. Otherwise, the resulting assembly code may be wrong. You can refer to the two "r" in the above example ", change to "m" (m indicates that the operands are stored in the memory, rather than in the register). After compilation, the result is:
Movl input, result
Obviously this is an invalid instruction, so the character string must match the instruction's requirements on the operand. For example, the instruction movl allows the Register to the Register and the register to be counted immediately, but the memory to the memory operation is not allowed. Therefore, the two operands cannot use "m" as the delimiter at the same time.

The embedded assembly syntax is as follows:
_ Asm _ (Assembly statement template: Output part: input part: Destroy description part)
There are four parts in total: The Assembly statement template, the output part, the input part, and the destruction description part. Each part uses the ":" lattice. The Assembly statement template is required. The other three parts are optional, if the latter part is used, and the former part is empty, you must use the ":" format. The content of the corresponding part is empty. For example:
_ Asm _ volatile _ ("cli": "memory ")

1. Assembly statement Template
An assembly statement template consists of a sequence of Assembly statements, separated by ";", "\ n", or "\ n \ t. The operands in the command can use placeholders to reference C language variables. A maximum of 10 operands can be placeholders named as follows: % 0, % 1,..., % 9. Operations expressed by placeholders in a command are always considered as long (4 bytes). However, operations on the command can be a word or byte, when the operand is used as a word or byte, the default value is low or low. The Byte operation can explicitly specify whether it is a low byte or a secondary byte. Insert a letter between % and serial number. "B" indicates low bytes, and "h" indicates high bytes, for example, % h1.

2. Output part
The output part describes the output operands. Different operands are separated by commas. each operand descriptor consists of a limited string and a C-language variable. The limited string of each output operand must contain "=", indicating that it is an output operand.
Example:
_ Asm _ volatile _ ("pushfl; popl % 0; cli": "= g" (x ))
The descriptor string represents the constraints on the variable, so that GCC can determine how to allocate registers based on these conditions, and how to generate the connection between the necessary code Processing Instruction operands and C expressions or C variables.

3. Input
The input part describes the input operands. Different operands are separated by commas (,). Each operand descriptor consists of a limited string, a C expression, or a C variable.
Example 1:
_ Asm _ volatile _ ("lidt % 0": "m" (real_mode_idt ));
Example 2 (bitops. h ):


Static _ inline _ void _ set_bit (int nr, volatile void * addr)
{
_ Asm __(
"Btsl % 1, % 0"
: "= M" (ADDR)
: "Ir" (nr ));
}

The following example sets the nr bit of (* addr) to 1. The first placeholder % 0 corresponds to the C language variable ADDR, and the second placeholder % 1 corresponds to the C language variable nr. Therefore, the Assembly statement code above is equivalent to the pseudo code below: btsl nr, ADDR. The two operands of this command cannot be all memory variables. Therefore, the qualified string of nr is specified as "Ir ", associate nr with the immediate number or register, so that only ADDR is the memory variable in the two operands.

4. Restricted characters
4.1. Restricted Character List
There are many types of restricted characters, some of which are related to the specific architecture. Here, only the commonly used qualified characters and some common qualifiers that may be used in i386 are listed. They are used to indicate how the compiler processes the relationship between the subsequent C language variables and the instruction operands.

CATEGORY qualifier description
General registers"A" put the input variable into eax
Here is a question: what if eax has been used?
In fact, it is very simple: because GCC knows that eax has been used, it assembles the code in this section
Insert a statement pushl % eax at the beginning of, save the eax content to the stack
Then add a statement popl % eax at the end of the Code to restore the content of eax.
"B" puts input variables in ebx
"C" puts input variables into ecx
"D" put the input variable in edx
"S" puts the input variable into esi
"D" put input variables into edi
"Q": Put the input variables in one of eax, ebx, ecx, and edx.
"R" puts the input variables into the General registers, that is, eax, ebx, ecx,
One of edx, esi, and edi
"A" combines eax and edx into A 64-bit register (use long longs)

Memory"M" memory variable
The "o" operand is a memory variable, but its addressing method is offset type,
That is, base address addressing, or base address plus address change addressing
The "V" operand is a memory variable, but the addressing mode is not an offset type.
"" The operand is a memory variable, but the addressing mode is auto increment.
The "p" operand is a valid memory address (pointer)

Register or memory"G" puts the input variables into one of eax, ebx, ecx, and edx.
Or as a memory variable
The "X" operand can be of any type.

Instant count
"I" 0-31 immediate count (for 32 shift bit instructions)
"J" immediate number between 0 and 63 (for 64-bit displacement instructions)
Immediate number between "N" and 0-(used for the out command)
"I" immediate count
"N": immediate number. Some systems do not support immediate numbers except words,
These systems should use "n" instead of "I"

Match"0" indicates that the operands restricted by it match a specified operand,
"1"... that is, the specified operand, for example, "0"
"9" to describe "% 1" operations, then "% 1" references actually
Is the operand of "% 0". Note that the 0-9 and
The difference between "% 0"-"% 9" in the command. The former describes the operands,
The latter represents the operands.
& The output operations cannot use registers that are the same as the input operations.

Operand type"=" The operand is written only in the instruction (the output operand)
"+" Operations are read/write type in the instruction (input/output operations)

Floating Point Number"F" floating point register
"T" first floating-point register
"U" second floating point register
"G" Standard 80387 floating point constant
% This operand can be switched to the next operand
For example, the two operands of addl can exchange order.
(Of course, neither of the two operands can be an immediate number)
# Partial comments. All letters from this character to the comma after it are ignored
* Indicates that if a register is selected, the subsequent letters are ignored.

5. Damage description
The destroy descriptor is used to notify the Compiler which registers or memory are used. It is composed of comma-separated strings. Each string describes a situation, generally the register name; in addition to registers, there is also "memory ". For example, "% eax", "% ebx", and "memory.

"Memory" is special and may be the most difficult part of Embedded Assembly. To explain it clearly, first introduce the compiler optimization knowledge, and then look at the C keyword volatile. Finally, let's look at the descriptor.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.