Embedded Assembly macro function _ syscall0 for system calls defined in linux/include/unistd. h.
In fact, it is not difficult to find that it is a function, but it is defined by a macro. The key is how to understand the syntax of _ asm _ volatile. For the fixed form of _ asm _ volatile, we temporarily ignore it (can refer to the http://blog.csdn.net/robbie1314/archive/2011/04/17/6329880.aspx), the key to understand the meaning in.
The following is an example to briefly introduce this usage.
The code snippets inserted into a C language assembly can be divided into four parts, separated by the ":" number, the general form is:
Command: Output: input: damaged
Static _ inline _ void atomic_add (int I, atomic_t * v)
{
_ Asm_volatile __(
LOCK "addl % 1, % 0"
: "= M" (v-> counter)
: "Ir" (I), "m" (v-> counter ));
}
When the Assembly Language code is embedded into the C code, it is a problem to solve the combination of the operands and the variables in the C code. We cannot know exactly which register gcc will allocate to which variable before and after the embedded point. So gcc adopts one method: the programmer only provides specific instructions, the use of registers generally only provides a "sample" and some constraints. In the end, how to combine variables and operands is left to gcc and gas for processing.
Command Department
The number is prefixed with %, such as % 1 and % 0, indicating that the Register's sample operand is required. The total number of such operations that can be used depends on the number of General registers in the CPU.
Output Department
Specifies the constraints on the output variable, that is, how the target operand is combined. Each such condition is called a "constraint condition ". If necessary, the output department may have multiple constraints separated by commas.Each output constraint starts with "=", followed by a letter indicating the operand type, followed by a constraint on variable combination. In the example:
: "= M" (v-> counter)
There is only one constraint. "= m" indicates that the target operand (% 0 in the instruction) is a memory unit v-> counter.
Input
The format of the input constraint is similar to that of the output constraint without the "=" sign. In the example:
The 1st values are "ir" (I), indicating that % 1 in the instruction can be a "direct operand" (I indicates immediate) in the register ), and the operand comes from the variable name in the C code (the call parameter here) I.
The 2nd constraint condition "m" (v-> counter) is of the same meaning as the input constraint.
Damaged Department
In some operations, in addition to the registers used for input and output operations, several registers are also used for calculation or intermediate results of operations. In this way, the original content of these registers is corrupted. Therefore, we need to describe the side effects of the operation in the corrupt part so that gcc can take appropriate measures. However, sometimes these instructions are directly put in the output part, and that is not necessary.
The number of the operand starts from the first constraint in the output part (the number is 0). The number of the operands is counted in sequence, and each constraint is added once. When you reference these operands in the instruction department or assign registers for these operands, add % before the sequence number.
There are many letters that indicate constraints, mainly including:
"M", "v", and "o" ---- memory unit
"R" ---- indicates any register
"Q" ---- one of the registers eax, ebx, ecx, and edx
"I" and "h" ---- represents the direct operand
"E" and "F" ---- indicates a floating point number.
"G" ---- indicates arbitrary
"A", "B", "c" d "---- register eax ebx ecx and edx respectively
"S" and "D" ---- respectively indicate to use the register esi and edi
"I" ---- represents a constant (0 to 31)
Return to the example above. The function of this Code is to add the value of parameter I to v-> counter. The keyword LOCK of the Code indicates that the system bus should be locked when the addl command is executed, so as to ensure atomic operations without disturbing other CPUs.
Below we can follow the instructions above to understand the following code.
Code:
/* The following definition system calls Embedded Assembly macro functions */
/* Macro functions are called without parameters. Type name (void ).
* % 0-eax (_ res), % 1-eax (_ NR _ # name ). The name is the name of the system call.
* It is commonly used to form the above system call symbol in combination with _ NR _ to address the function pointer in the system call table.
* Call System interruption 0x80, return value-> eax (_ res), input as system interruption call number _ NR_name
* Return: If the returned value is greater than or equal to 0, this value is returned. Otherwise, the error code errno is set and-1 is returned.
*/
# Define _ syscall0 (type, name )/
Type name (void )/
{/
Long _ res ;/
_ Asm _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "" (_ NR _ # Name ));/
If (_ res> = 0 )/
{/
Return (type) _ res ;/
}/
Errno =-_ res ;/
Return-1 ;/
}
/* Macro functions with one parameter are called by the system. Type name (Atype)
* % 0-eax (_ res), % 1-eax (_ nr_name), % 2-EBX ()
*/
# DEFINE _ syscall1 (type, name, Atype, )/
Type name (Atype )/
{/
Long _ res ;/
_ ASM _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "" (_ NR _ # name), "B" (long) ()));/
If (_ res> = 0 )/
{/
Return (type) _ res ;/
}/
Errno =-_ res ;/
Return-1 ;/
}
/* Macro functions with two parameters are called by the system. Type name (Atype A, btype B)
* % 0-eax (_ res), % 1-eax (_ nr_name), % 2-EBX (A), % 3-ECx (B)
*/
# DEFINE _ syscall2 (type, name, Atype, A, btype, B )/
Type name (Atype A, btype B )/
{/
Long _ res ;/
_ ASM _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "" (_ NR _ # name), "B" (long) (a), "C" (long) (B )));/
If (_ res> = 0 )/
{/
Return (type) _ res ;/
}/
Errno =-_ res ;/
Return-1/
}
/* Macro functions with three parameters are called by the system. Type name (Atype A, btype B, ctype C)
* % 0-eax (_ res), % 1-eax (_ nr_name), % 2-EBX (A), % 3-ECx (B ), % 4-EDX (c)
*/
# DEFINE _ syscall3 (type, name, Atype, A, btype, B, ctype, C )/
Type name (Atype A, btype B, ctype C )/
{/
Long _ res ;/
_ ASM _ volatile ("int $0x80 "/
: "= A" (_ res )/
: "" (_ NR _ # name), "B" (long) ()),/
"C" (long) (B), "D" (long) (c )));/
If (_ res> = 0 )/
{/
Return (type) _ res ;/
}/
Errno =-_ res ;/
Return-1 ;/
}