asm__volatile()在Linux内核
可以请人解释究竟这个功能是干什么的,我试图谷歌,但一无所获:asm__volatile()在Linux内核
long __res; //some variable
__asm__ volatile (
"movl $244, %%eax;"
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
"int $0x80;"
"movl %%eax,%0"
: "=m" (__res) //from here can't understand
: "m" (a), "m" (b) , "m" (c)
: "%eax","%ebx","%ecx", "%edx",
);
先感谢您的任何解释
服用这一步一步:
long __res; //some variable
__asm__ volatile (
"movl $244, %%eax;"
...通过%eax
中的值选择32位x86 Linux的系统调用。这是系统调用的号码get_thread_area
。请参阅arch/x86/include/asm/unistd_32.h
(在最近的内核中)获取系统调用号列表。 (注:系统调用号码不是32位和64位之间是相同的。)
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
...参数到系统调用在寄存器传递。对于32位x86,在寄存器中最多传递5个参数,顺序为%ebx
,%ecx
,%edx
,%esi
,%edi
(对于需要它的少数系统调用的第6个参数在用户堆栈上传递)。 %1
,%2
,%3
指内联汇编程序的“约束”中提到的第2,3和4项(见下文)。
(这似乎有点奇怪,顺便说一句:在get_thread_area
系统调用only needs one argument ...)
"int $0x80;"
...调用系统调用。
"movl %%eax,%0"
...系统调用返回结果%eax
; %0
是指约束中提到的第一个项目。
: "=m" (__res) //from here can't understand
...“约束”告诉GCC其中它可以把所使用和产生由联汇编器块中的输入和输出值。这第一部分(在第一个:
之后)用于输出。 "=m"
这里说__res
应该保存在内存中("m"
),并且它是只写的,即任何以前的值将被覆盖("="
)。约束中的操作数可以通过内联汇编块中的数字引用(例如,%0
),从0开始出现。
: "m" (a), "m" (b) , "m" (c)
...下一部分是输入。这表示他们将全部置于记忆中。
: "%eax","%ebx","%ecx", "%edx",
...最后一节中表示“打一顿”寄存器,即,那些将被覆盖为一体的内联汇编块内的代码的结果。 GCC会将嵌入式汇编程序块放入其生成的其他代码的中间,但它不知道块内部的指令实际上做了什么 - 因此您必须告诉它,任何可能在封锁将不再有效。
);
这个函数是执行系统调用(由于x86 int 0x80
)。
你标记的部分是GCC联汇编器助手 - 其允许被C名给出,在此情况下,__res, a, b, c
GCC改变占位符(%0-%3)的实际值。
您可以了解确切的内联汇编语法在这里:
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
非常感谢您的回答,只有一个关于clobbered寄存器的问题,我的GCC会在覆盖之前保存它们? – likeIT 2011-04-07 07:55:25
@likeIT:是的,如果需要,GCC会自行保存它们。 – 2011-04-07 19:58:48