Ale*_*oba 4 assembly gcc sse x86-64 sse2
我有C函数做一些SSE计算.当我用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
Run Code Online (Sandbox Code Playgroud)
查看movaps说明 - 它是堆栈顶部的访问内存:
movaps %xmm15,-0x18(%rsp)
Run Code Online (Sandbox Code Playgroud)
它不是访问未定义的内存吗?为什么GCC生成了这样不正确的代码?
在装配级别没有"未定义的内存"这样的东西.只要行为符合预期,gcc就可以自由发出以其认为合适的方式访问堆栈的代码.
我猜测为什么会这样,这是一个叶子函数,调整堆栈指针是徒劳的.您可以尝试通过检查程序集的任何call指令来验证.(您也可以检查C源,但内联可能会使其不那么可靠.)
某些平台的ABI明确允许这种欺骗,包括x86-64.从AMD64 ABI文档:
超出%rsp指向的位置的128字节区域被认为是保留的,不应被信号或中断处理程序修改.因此,函数可以将此区域用于函数调用不需要的临时数据.特别是,叶子函数可以将这个区域用于它们的整个堆栈帧,而不是调整序言和尾声中的堆栈指针.这个区域被称为红区.
这篇博客文章可能会对这个主题进行有趣的阅读.