Assembly GCC访问栈顶以上的内存

Assembly GCC访问栈顶以上的内存,assembly,gcc,x86-64,sse,red-zone,Assembly,Gcc,X86 64,Sse,Red Zone,我有一个做SSE计算的C函数。当我用GCC编译它时,我会得到下一个代码 /* Start of function */ mov (%rdi),%rax movslq %ecx,%rcx ... mov 0x8(%rdi),%rax pxor %xmm12,%xmm3 movaps %xmm0,-0x28(%rsp) movaps %xmm6,%xmm1 ... movaps 0x50(%rax,%rcx,1),%xmm2 movaps 0x60(%rax,%rcx,1),%xmm

我有一个做SSE计算的C函数。当我用GCC编译它时,我会得到下一个代码

/* Start of function */
mov    (%rdi),%rax
movslq %ecx,%rcx
...
mov    0x8(%rdi),%rax
pxor   %xmm12,%xmm3
movaps %xmm0,-0x28(%rsp)
movaps %xmm6,%xmm1
...
movaps 0x50(%rax,%rcx,1),%xmm2
movaps 0x60(%rax,%rcx,1),%xmm15
pxor   %xmm2,%xmm0
pxor   %xmm2,%xmm6
movaps -0x28(%rsp),%xmm2
pxor   %xmm15,%xmm5
pxor   %xmm15,%xmm2
movaps 0x70(%rax,%rcx,1),%xmm15
movaps (%rax,%rcx,1),%xmm11
mov    0x10(%rdi),%rax
movaps %xmm15,-0x18(%rsp)
pxor   %xmm11,%xmm4
pxor   %xmm12,%xmm11
pxor   %xmm15,%xmm12
查看
movaps
说明-它是堆栈顶部的访问内存:

movaps %xmm15,-0x18(%rsp)
这不是对未定义内存的访问吗?为什么GCC生成了如此错误的代码?

在程序集级别没有“未定义内存”这样的东西。gcc可以自由地发出代码,以它认为合适的任何方式访问堆栈,只要行为符合预期

我想这是因为这是一个叶函数,调整堆栈指针是徒劳的。您可以通过检查程序集中是否有任何
调用
指令来验证这一点。(您也可以检查C源代码,但内联可能会降低可靠性。)

某些平台(包括x86-64)的ABI明确允许这种欺骗。发件人:

将考虑%rsp指向的位置以外的128字节区域 保留,不得通过信号或中断进行修改 处理程序。因此,函数可以将此区域用于临时数据 这在函数调用中是不需要的。尤其是叶 函数可以将此区域用于其整个堆栈帧,而不是 在序言和尾声中调整堆栈指针。这个地区是 被称为红色区域


可能有助于对该主题进行有趣的阅读。

函数中是否有其他指令(特别是在序言或各种退出点中)以各种方式调整
%rsp
。我可能猜,对于函数中的某个特定块/循环,
%rsp
被向下调整,以便为一些临时变量腾出空间,此时,它已经被调整回原来的位置,但是
gcc
知道它还没有覆盖这些位置,所以它仍然可以自由访问它们。或者创建一些临时变量而不用费心调整
%rsp
。。。优化可以做一些看起来很奇怪的事情…@twalberg nope,
%rsp
在这个函数和调用后的任何地方都没有调整。它确实是叶函数。但真正的问题是,这实际上是内核模块函数,因此我认为其他线程或内核本身可以访问
rsp
上面的内存。我明白了,这才是最困扰我的。我对内核ABI一无所知,但x86-64 ABI中有一个子句允许在堆栈指针下方的某个固定大小内进行访问,目的是允许对叶函数进行优化。我会编辑一些参考资料…你是对的,非常感谢!问题在于数据损坏,因为中断处理程序正在覆盖堆栈帧。引用自:历史上,中断处理程序并没有收到自己的堆栈。相反,他们将共享他们中断的进程堆栈。所以,当我用
-mno red zone
编译代码时,它开始正常工作。哦,这听起来是一个有趣的问题!很高兴听到它被整理出来。@AlexanderDzyoba:是的,-中断对堆栈的硬件使用。