红色区域是内存中超出“未分配”堆栈指针的固定大小区域。编译器确实会生成汇编程序,以通过简单的叶函数访问该区域。
但是我看不出红色区域有任何真正的优势。在堆栈指针之外访问内存确实很危险,并且很容易导致数据损坏。为什么还要这样做?保存2条处理器指令(push ebp; mov ebp esp)不会真正提高速度。
红色区域是内存中超出“未分配”堆栈指针的固定大小区域。编译器确实会生成汇编程序,以通过简单的叶函数访问该区域。
但是我看不出红色区域有任何真正的优势。在堆栈指针之外访问内存确实很危险,并且很容易导致数据损坏。为什么还要这样做?保存2条处理器指令(push ebp; mov ebp esp)不会真正提高速度。
Answers:
纯粹是简单地,红色区域是可以保存指令的优化。这意味着不再需要为每个函数所发出的代码从堆栈指针中减去以进行本地存储,就像这样
sub XXX, %rsp
在每个函数调用的开始,即使它们不是叶函数也是如此。通常,从编译器发出的代码可以使用堆栈指针下方红色区域中的临时空间,而无需保存它并在调用其他函数之前。这是有用的优化。
如果您不再需要从堆栈指针中继承,则发出的代码可以将rsp用作基本指针,这通常是为rbp保留的作业,发出的代码可以将rbp用作另一个通用寄存器。
这最终意味着每个函数调用的序言和结尾都可以保存两条指令,这些指令可以保存和恢复rbp:
(gnu汇编程序)
pushq %rbp # prologue [ two instructions not necessary ]
movq %rsp,%rbp
.... [code]
movq %rbp,%rsp # epilogue [ two instructions not necessary ]
popq %rbp
请注意,在gcc中,如果您不需要它,则可以传递-mno-red-zone标志(但是x86-64 ABI要求它)。Linux内核不需要与ABI兼容,因此所有内核代码都使用-mno-red-zone进行编译。
此外,如果这是预期的操作模式,则访问超出堆栈指针的内存并不危险。这只是危险,在计划外和意外的情况下可能导致腐败。当发出的代码执行此操作时,它知道它在做什么。
%rsp
两种方法中的任何一种作为基本指针来索引堆栈。