Article Title: x86 inline assembly in Linux. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
X86 inline assembly in Linux
Combine all parts
DeveloperWorks
Document options
Send this page as an email
Latest recommendations
Java application development source power-download free software and start development quickly
Level: elementary
Bharata B. RaoIBM Linux technology center, IBM software lab, India
Bharata B. Rao provides a general introduction to using and constructing x86 inline assembly on the Linux platform. He introduced the basic knowledge of inline assembly and its usage, provided some basic guidance on inline assembly encoding, and explained some examples of inline assembly code in the Linux kernel.
If you are a Linux kernel developer, you will find that you often need to encode or optimize the code path for features highly relevant to the architecture. You may execute these tasks by inserting assembly language instructions into the middle of the C statement (also known as an inline assembly method. Let's take a look at the specific usage of inline assembly in Linux. (We will discuss the limitations in IA32 compilation .)
GNU Assembler
Let's first take a look at the basic assembler syntax used in Linux. GCC (gnu c compiler for Linux) uses the AT&T Assembly syntax. Some basic rules of this syntax are listed below. (The list must be incomplete. It only includes the rules related to inline assembly .)
Register name
Register names are prefixed with %. That is, if you must use eax, it should be used as % eax.
Sequence of source and destination operands
In all commands, the source and target operations are performed first. This is different from the Intel syntax that places the source operand after the destination operand.
Mov % eax, % ebx, transfers the contents of eax to ebx.
Number of operations
The instruction suffix can be B, w, or l based on whether the operand is byte, word, or long. this is not mandatory; GCC will try to provide the corresponding suffix by reading the operands. However, manually specifying a suffix can improve code readability and eliminate the possibility of incorrect compiler guesses.
Movb % al, % bl -- Byte move
Movw % ax, % bx -- Word move
Movl % eax, % ebx -- Longword move
Immediate operand
Use $ to specify the direct operand.
Movl $0 xffff, % eax -- will move the value of 0 xffff into eax register.
Indirect Memory Reference
Any indirect reference to memory is done by using.
Movb (% esi), % al -- will transfer the byte in the memory
Pointed by esi into al
Register
Inline assembly
GCC provides a special structure for inline assembly, which has the following format:
The "asm" structure of GCG
Asm (aggreger template
: Output operands (optional)
: Input operands (optional)
: List of clobbered registers
(Optional)
);
In this example, the assembler template consists of Assembly commands. The input operand is the C expression used to act as the input operand. The output operand is the C expression that will execute the Assembly command output on it.
The importance of inline assembly is that it can be flexibly operated, and its output can be displayed through the C variable. Because it has this capability, "asm" can be used as an interface between assembly instructions and C Programs that contain it.
A very basic but important difference is that simple inline assembly only includes instructions, while extended inline assembly includes operands. To illustrate this, consider the following example:
Basic elements of inline assembly
{
Int a = 10, B;
Asm ("movl % 1, % eax;
Movl % eax, % 0 ;"
: "= R" (B)/* output */
: "R" (a)/* input */
: "% Eax");/* clobbered register */
}
In the preceding example, we use an assembly command to make the value of "B" equal to "a". Note the following:
* "B" is the output operand, referenced by % 0, and "a" is the input operand, referenced by % 1.
* "R" is the operand constraint, which specifies that the variables "a" and "B" are stored in registers. Note that the output operand constraint should contain a constraint modifier "=", specifying that it is the output operand.
* To use register % eax in "asm", add % before % eax, in other words % eax, because "asm" uses % 0, % 1, and so on to identify variables. Any number with one % is considered as an input/output operand, not a register.
* The modifier register % eax after the third colon tells that the GCC % eax value will be modified in "asm", so that GCC will not use this register to store any other value.
* Movl % 1, % eax move the value of "a" to % eax, movl % eax, % 0 move the content of % eax to "B.
* Because "B" is specified as the output operand, when "asm" is executed, it will reflect the updated value. In other words, changes made to "B" in "asm" will be reflected out of "asm.