ng.*_*bie 0 linux x86 gcc linux-kernel function-attributes
在大多数语言中,C 包括堆栈用于函数调用。这就是如果您在递归时不小心会收到“堆栈溢出”错误的原因。(不是双关语)。
如果这是真的,那么asmlinkageGCC 指令有什么特别之处。
它说,来自#kernelnewbies
asmlinkage 标签是我们应该注意的关于这个简单函数的另一件事。这是一些 gcc 魔法的 #define,它告诉编译器该函数不应期望在寄存器中找到它的任何参数(一种常见的优化),而只能在 CPU 的堆栈上。
我的意思是我不认为寄存器用于正常的函数调用。
更奇怪的是,当你了解到它是在 x86 上使用 GCC regparm 函数属性实现的。
regparm的文档如下:
在 x86-32 目标上,如果参数在寄存器 EAX、EDX 和 ECX 中而不是在堆栈中是整数类型,则 regparm 属性会导致编译器将第一个参数传递给 number。
这基本上与asmlinkage正在尝试做的相反。
那么会发生什么?它们是在堆栈上还是在寄存器上。
我哪里错了?
信息不是很清楚。
通常,为了使调用更快(取决于体系结构),编译器可以选择通过寄存器传递一些参数,以避免每次都将它们复制到/从堆栈中复制。对于未导出的私有函数尤其如此,因此不需要遵守 ABI 定义的调用约定,以便进一步优化。
一些 ABI 实际上需要在寄存器中传递参数。System V AMD64 ABI 调用约定(Linux x86-64 上的默认值)就是一个很好的例子:它规定函数参数应该通过 RDI、RSI、RDX、RCX、R8、R9、[XYZ]MM0-7、所以堆栈很少使用。
现在,在 Linux 中进行系统调用时,内核会复制堆栈上的用户空间寄存器以保留它们,然后调用适当的系统调用函数。这些函数应直接从堆栈中已保存的用户寄存器中获取参数,因此必须编译为仅且始终从堆栈中获取参数。
在 x86 32bit 中,asmlinkage宏扩展为 __attribute__((regparam(0))),这基本上告诉 GCC不应该通过寄存器传递参数(这0是重要的部分)。在 x86 64 位上,它扩展为更具体的__attribute__((syscall_linkage))。最终结果是一样的:函数被迫从堆栈中获取参数。在其他总是在堆栈上传递参数的架构上,__attribute__甚至不需要特殊的东西。
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |