![](/img/trans.png)
[英]What's the meaning for this inline assembly (:“0” (THREAD_SIZE - 1)) in linux kernel 2.6.11 for i386
[英]How does kernel_thread_helper pass parameters to kernel thread function using inline assembly?
我正在閱讀版本 2.6.11 的 linux kernel 的源代碼,並對arch/i386/kernel/process.c
中的內聯匯編kernel_thread_helper
感到困惑。
以下是匯編代碼。 最初,寄存器%ebx
存儲 function 的地址,寄存器%edx
存儲將傳遞給 function 的指針。
extern void kernel_thread_helper(void);
__asm__(".section .text\n"
".align 4\n"
"kernel_thread_helper:\n\t"
"movl %edx,%eax\n\t"
"pushl %edx\n\t"
"call *%ebx\n\t"
"pushl %eax\n\t"
"call do_exit\n"
".previous");
我在想:
為什么這段代碼會執行movl %edx,%eax
? 由於pushl %edx
已將 % %edx
的值推送到堆棧中,因此%ebx
指向的 function 應該會成功地從堆棧中檢索所需的參數。 那么是否不需要將%edx
復制到%eax
?
我知道當在 function 定義前面添加__attribute__((regparm(3)))
時,function 將按%eax
、 %edx
、 %ecx
和堆棧的順序檢索參數。 所以我想知道,將%edx
中的值復制到%eax
的指令是否旨在與使用此__attribute__
的函數兼容? 具有這樣一個屬性的 Function 應該在運行時從%eax
和 go 檢索所需的參數:但這會導致一個問題,如果沒有人將其彈出,先前由pushl %edx
壓入的指針可能會保留在堆棧中。
我是 Linux Kernel 的新手,可能誤解了一些東西。 我想知道這些匯編指令實際上是如何工作的,以及我的猜測有什么問題。
較早的 Linux kernel 版本(v2.5.0)中的評論解釋了這一點( 在 v2.1.131 中添加了movl
into eax
以真正准確):
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
long retval, d0;
__asm__ __volatile__(
"movl %%esp,%%esi\n\t"
"int $0x80\n\t" /* Linux/i386 system call */
"cmpl %%esp,%%esi\n\t" /* child or parent? */
"je 1f\n\t" /* parent - jump */
/* Load the argument into eax, and push it. That way, it does
* not matter whether the called function is compiled with
* -mregparm or not. */
"movl %4,%%eax\n\t"
"pushl %%eax\n\t"
"call *%5\n\t" /* call fn */
"movl %3,%0\n\t" /* exit */
"int $0x80\n"
"1:\t"
:"=&a" (retval), "=&S" (d0)
:"0" (__NR_clone), "i" (__NR_exit),
"r" (arg), "r" (fn),
"b" (flags | CLONE_VM)
: "memory");
return retval;
}
所以是的,正如您所懷疑的那樣, movl
into eax
正是為使用-mregparam
或等效的__attribute__
編譯的兩個函數提供兼容性,而沒有(i386 System V ABI 調用約定,即堆棧上的所有參數)。
但這會導致一個問題:如果沒有人將其彈出,則
pushl %edx
先前推送的指針可能會保留在堆棧中。
好吧,沒錯,但是如果我們在調用 kernel 線程 function 之后唯一要做的事情是pushl %eax; call do_exit
pushl %eax; call do_exit
? 執行movl %eax, 0(%esp)
也可以,但是如果有足夠的堆棧空間來運行 kernel 線程,那么在它返回后肯定有 4 個字節來推送寄存器。 此外pushl %eax
只有 1 個字節,而movl
是 3 個字節,我不確定兩者的延遲或吞吐量,但我真的不認為這是這樣一段代碼的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.