我们为什么需要堆栈分配,当我们有一个红色区域? [英] Why do we need stack allocation when we have a red zone?

查看:244
本文介绍了我们为什么需要堆栈分配,当我们有一个红色区域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下疑问:

正如我们所知道的System V ABI X86-64给了我们关于一个固定大小的区域(128字节)的堆栈帧,所谓的redzone后面。
所以,作为一个结果,我们并不需要使用,例如,子RSP,12 。只要 MOV [RSP-12,X 而这一切。

但我不能掌握这一想法。为什么这有关系?是否有必要子RSP,12 没有redzone后面?毕竟,堆栈大小在一开始的限制,为什么子RSP,12 是非常重要的?我知道,它能使我们跟随堆栈的顶部,但让我们忽略它的那一刻。

我知道一些指令使用什么 RSP 值(如 RET ),但不关心它时刻。

问题的关键是:
我们没有redzone后面,我们所做的:

 函数:
    MOV [RSP-16],RCX
    MOV [RSP-32],RCX
    MOV [RSP-128],RCX
    MOV [RSP-1024],RCX
    RET

是它区别?

 函数:
    子RSP,1024
    MOV [RSP-16],RCX
    MOV [RSP-32],RCX
    MOV [RSP-128],RCX
    MOV [RSP-1024],RCX
    加RSP,1024
    RET


解决方案

在红番区,是不是绝对必要的。在你来说,它可以被认为是毫无意义的。你可以做用红色区域的一切,你也可以做,你这样做是针对IA-32 ABI的传统方式。

下面就是在 AMD64 ABI 说,有关的红色区域:


  

128字节区域以外的位置,由%RSP 指出,被认为是保留的,不得通过信号或中断处理程序进行修改。因此,函数可以使用该区域未在函数调用所需的临时数据。尤其是,叶函数可以使用此区域为他们的整个堆栈帧,而不是在序幕和尾声调整堆栈指针。这个区域被称为红色区域。


  
  


红色区域的真正目的是为的优化的。它的存在让code的假设,128字节以下 RSP 将不会被异步地信号惨败或中断处理,这使得它可以使用它作为暂存空间。这使得它无需通过 RSP 移动堆栈指针明确在栈上创建暂存空间。这是一个优化,因为指令递减和恢复 RSP 现在可以省略掉,节省了时间和空间。

所以,是的,当你的可能的做到这一点与AMD64(并需要与IA-32这样做):

 函数:
    推RBP;标准的序幕保存
    MOV RBP,RSP; RSP原值    子RSP,32;堆栈储备从无到有区
    MOV QWORD PTR [RSP],RCX;副本RCX到我们的刮开区
    MOV QWORD PTR [RSP + 8],RDX; RDX复制到我们的刮开区    ; ...做一些事情,则会覆盖RCX和RDX ...    RCX MOV [RSP]从我们的刮开区检索RCX原值
    RDX MOV [RSP + 8];从我们的刮开区检索RDX原值
    加RSP,32;还给我们作为临时区域堆栈空间    流行RBP;标准的尾声来恢复RSP
    RET

我们不这样做的需求的做这件事的情况下,我们只需要一个128字节的临时区域(或更小),因为这时我们可以使用红色区域作为我们的临时区域。

另外,因为我们不再递减堆栈指针,我们可以使用 RSP 作为基指针(而不是 RBP ),因此不必保存和恢复 RBP (在序幕和尾声),同时还释放了 RBP 用作另一个通用寄存器!

(从技术上来说,打开帧指针省略( -fomit-frame-pointer的,默认情况下使用 -O1 自ABI允许)也将有可能使编译器的Elid的序幕和尾声部分,用同样的好处。但是,如果没有一个红色区域,需要调整堆栈指针预留空间不会改变。 )

请注意,但是,ABI的唯一保证类似信号异步的东西和中断处理程序不得修改红色区域。调用其它功能可能在红色区域揍价值,所以不是特别有用,但在叶函数(那些不会调用任何其他功能,因为如果他们在一个函数调用树叶子功能)


一个最后一点:的Windows x64 ABI <一个href=\"http://stackoverflow.com/questions/4429398/why-does-windows64-use-a-different-calling-convention-from-all-other-oses-on-x86\">deviates稍微从AMD64 ABI在其他操作系统上使用。尤其是,它没有一个红色区域的概念。超越 RSP 该地区被认为是不稳定,随时可能被覆盖。相反,它要求调用方分配堆栈上的家庭地址空间中,然后可用于被叫方的事件使用的,它需要溅出的寄存器传递的参数。

I have the following doubts:

As we know System V x86-64 ABI gives us about a fixed-size area (128 bytes) in the stack frame, so called redzone. So, as a result we don't need to use, for example, sub rsp, 12. Just make mov [rsp-12], X and that's all.

But I cannot grasp idea of that. Why does it matter? Is it necessary to sub rsp, 12 without redzone? After all, stack size is limited at the beginning so why sub rsp, 12 is important? I know that it makes possible us to follow the top of the stack but let's ignore it at that moment.

I know what some instructions use rsp value ( like ret) but don't care about it in that moment.

The crux of the problem is: We have no redzone and we've done:

function:
    mov [rsp-16], rcx
    mov [rsp-32], rcx
    mov [rsp-128], rcx
    mov [rsp-1024], rcx
    ret

Is it difference with?

function:
    sub rsp, 1024
    mov [rsp-16], rcx
    mov [rsp-32], rcx
    mov [rsp-128], rcx
    mov [rsp-1024], rcx
    add rsp, 1024
    ret

解决方案

The "red zone" is not strictly necessary. In your terms, it could be considered "pointless." Everything that you could do using the red zone, you could also do the traditional way that you did it targeting the IA-32 ABI.

Here's what the AMD64 ABI says about the "red zone":

The 128-byte area beyond the location pointed to by %rsp is considered to be reserved and shall not be modified by signal or interrupt handlers. Therefore, functions may use this area for temporary data that is not needed across function calls. In particular, leaf functions may use this area for their entire stack frame, rather than adjusting the stack pointer in the prologue and epilogue. This area is known as the red zone.

The real purpose of the red zone is as an optimization. Its existence allows code to assume that the 128 bytes below rsp will not be asynchronously clobbered by signals or interrupt handlers, which makes it possible to use it as scratch space. This makes it unnecessary to explicitly create scratch space on the stack by moving the stack pointer in rsp. This is an optimization because the instructions to decrement and restore rsp can now be elided, saving time and space.

So yes, while you could do this with AMD64 (and would need to do it with IA-32):

function:
    push rbp                      ; standard "prologue" to save the
    mov  rbp, rsp                 ;   original value of rsp

    sub  rsp, 32                  ; reserve scratch area on stack
    mov  QWORD PTR [rsp],   rcx   ; copy rcx into our scratch area
    mov  QWORD PTR [rsp+8], rdx   ; copy rdx into our scratch area

    ; ...do something that clobbers rcx and rdx...

    mov  rcx, [rsp]               ; retrieve original value of rcx from our scratch area
    mov  rdx, [rsp+8]             ; retrieve original value of rdx from our scratch area
    add  rsp, 32                  ; give back the stack space we used as scratch area

    pop  rbp                      ; standard "epilogue" to restore rsp
    ret

we don't need to do it in cases where we only need a 128-byte scratch area (or smaller), because then we can use the red zone as our scratch area.

Plus, since we no longer have to decrement the stack pointer, we can use rsp as the base pointer (instead of rbp), making it unnecessary to save and restore rbp (in the prologue and epilogue), and also freeing up rbp for use as another general-purpose register!

(Technically, turning on frame-pointer omission (-fomit-frame-pointer, enabled by default with -O1 since the ABI allows it) would also make it possible for the compiler to elide the prologue and epilogue sections, with the same benefits. However, absent a red zone, the need to adjust the stack pointer to reserve space would not change.)

Note, however, that the ABI only guarantees that asynchronous things like signals and interrupt handlers not modify the red zone. Calls to other functions may clobber values in the red zone, so it is not particularly useful except in leaf functions (which those functions that do not call any other functions, as if they were at the "leaf" of a function-call tree).


A final point: the Windows x64 ABI deviates slightly from the AMD64 ABI used on other operating systems. In particular, it has no concept of a "red zone". The area beyond rsp is considered volatile and subject to be overwritten at any time. Instead, it requires that the caller allocate a home address space on the stack, which is then available for the callee's use in the event that it needs to spill any of the register-passed parameters.

这篇关于我们为什么需要堆栈分配,当我们有一个红色区域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆