Linux内核如何确定函数参数在CPU寄存器中的位置?

Linux内核如何确定函数参数在CPU寄存器中的位置?,linux,assembly,kernel,system-calls,calling-convention,Linux,Assembly,Kernel,System Calls,Calling Convention,我想知道Linux内核如何知道在执行系统调用时在哪个寄存器中查找函数参数。例如:我从程序集调用write系统调用。参数存储在rdi、rsi和rdx中。然后内核调用write函数,该函数看起来像writefd、buf、len 但是内核如何知道fd存储在rdi中,buf存储在rsi中,len存储在rdx中? 实施情况如何?内核中是否存在某种映射来初始化这些寄存器中的参数 我想我错过了什么。也许它甚至与这些寄存器无关? 我希望得到一些帮助:执行系统调用时,参数存储在x86_64调用约定中定义的寄存器中

我想知道Linux内核如何知道在执行系统调用时在哪个寄存器中查找函数参数。例如:我从程序集调用write系统调用。参数存储在rdi、rsi和rdx中。然后内核调用write函数,该函数看起来像writefd、buf、len

但是内核如何知道fd存储在rdi中,buf存储在rsi中,len存储在rdx中? 实施情况如何?内核中是否存在某种映射来初始化这些寄存器中的参数

我想我错过了什么。也许它甚至与这些寄存器无关?
我希望得到一些帮助:

执行系统调用时,参数存储在x86_64调用约定中定义的寄存器中。在*nix系统上,这些最有可能是SystemV。简单C函数的参数也存储在那里,因为编译器也遵循调用约定。因此,无需进行进一步处理即可将参数位置映射到C调用例程。

执行系统调用时,参数存储在x86_64调用约定中定义的寄存器中。在*nix系统上,这些最有可能是SystemV。简单C函数的参数也存储在那里,因为编译器也遵循调用约定。因此,无需进行进一步处理即可将参数位置映射到C调用例程。

这是架构调用约定的一部分。参数始终位于相同的寄存器中。内核知道,因为它被编程为从edi获取文件描述符,从rsi获取缓冲区,等等。@K.Sean内核入口点,即发生系统调用时执行的代码,通常在汇编中编写。它将这些寄存器的内容复制到一个结构中,供内核使用。可以使用内联汇编,但只需在普通的旧汇编中编写这些部分就更容易了。它将所有相关寄存器推送到堆栈上,然后从系统调用表调用一个系统调用,并传递一个指向该寄存器结构的指针。@K.Sean再次读取代码,我必须收回该代码。寄存器保存在堆栈上,是的。但只有这样,我们才能在返回用户空间时恢复它们。系统调用本身只是在中调用的一个C函数。由于系统调用参数与普通C函数的参数放在相同的寄存器中,除了使用r10 for rcx,但这是第196行中的地址,因此不需要特殊处理,系统调用代码用普通C编写。这是架构调用约定的一部分。参数始终位于相同的寄存器中。内核知道,因为它被编程为从edi获取文件描述符,从rsi获取缓冲区,等等。@K.Sean内核入口点,即发生系统调用时执行的代码,通常在汇编中编写。它将这些寄存器的内容复制到一个结构中,供内核使用。可以使用内联汇编,但只需在普通的旧汇编中编写这些部分就更容易了。它将所有相关寄存器推送到堆栈上,然后从系统调用表调用一个系统调用,并传递一个指向该寄存器结构的指针。@K.Sean再次读取代码,我必须收回该代码。寄存器保存在堆栈上,是的。但只有这样,我们才能在返回用户空间时恢复它们。系统调用本身只是在中调用的一个C函数。由于系统调用参数与普通C函数的参数放在相同的寄存器中,除了将r10用于rcx,但这是第196行中的地址,因此不需要特殊处理,系统调用代码用普通C编写。不太准确;x86-64 System V的函数调用约定将RCX用于第4个参数,但因为syscall指令会破坏RCX。但是是的,在x86-64 SystemV上大多数情况都是这样,但在i386上则不是这样,至少直到最近的内核总是使用C包装器进行分派,将保存的用户空间寄存器从条目保存的结构重新加载到内核。我想,这有一个小小的好处,就是对寄存器进行消毒,让用户空间更难注入任何可用于幽灵小工具的东西;x86-64 System V的函数调用约定将RCX用于第4个参数,但因为syscall指令会破坏RCX。但是是的,在x86-64 SystemV上大多数情况都是这样,但在i386上则不是这样,至少直到最近的内核总是使用C包装器进行分派,将保存的用户空间寄存器从条目保存的结构重新加载到内核。我想,这有一个小小的好处,就是对寄存器进行消毒,使用户空间更难注入任何可用于幽灵小工具的东西。