2011-04-06 178 views
2

可以請人解釋究竟這個功能是幹什麼的,我試圖谷歌,但一無所獲: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", 
); 

先感謝您的任何解釋

回答

4

服用這一步一步:

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

3

這個函數是執行系統調用(由於x86 int 0x80)。

你標記的部分是GCC聯彙編器助手 - 其允許被C名給出,在此情況下,__res, a, b, c GCC改變佔位符(%0-%3)的實際值。

您可以瞭解確切的內聯彙編語法在這裏:

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