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会将嵌入式汇编程序块放入其生成的其他代码的中间,但它不知道块内部的指令实际上做了什么 - 因此您必须告诉它,任何可能在封锁将不再有效。

); 
+0

非常感谢您的回答,只有一个关于clobbered寄存器的问题,我的GCC会在覆盖之前保存它们? – likeIT 2011-04-07 07:55:25

+0

@likeIT:是的,如果需要,GCC会自行保存它们。 – 2011-04-07 19:58:48

这个函数是执行系统调用(由于x86 int 0x80)。

你标记的部分是GCC联汇编器助手 - 其允许被C名给出,在此情况下,__res, a, b, c GCC改变占位符(%0-%3)的实际值。

您可以了解确切的内联汇编语法在这里:

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

你可以找到你需要了解和GCC内嵌汇编语法这里的所有信息:

http://www.ibm.com/developerworks/linux/library/l-ia.html