Was ist der Zweck der roten Zone?

12

Die rote Zone ist ein Bereich fester Größe im Speicher nach dem Stapelzeiger, der nicht "zugeordnet" wurde. Compiler generieren Assemblys, um in einfachen Blattfunktionen auf diesen Bereich zuzugreifen.

Aber ich sehe keine wirklichen Vorteile für die rote Zone. Der Zugriff auf Speicher jenseits des Stapelzeigers ist sehr gefährlich und kann leicht zur Beschädigung von Daten führen . Warum sogar das? Das Speichern von 2 Prozessoranweisungen (Drücken von ebp; mov ebp esp) führt nicht zu einer echten Beschleunigung.

Alexander Dzyoba
quelle

Antworten:

16

Die rote Zone ist einfach eine Optimierung, die Anweisungen speichern kann. Es bedeutet, dass der ausgegebene Code nicht mehr für jede Funktion vom Stapelzeiger subtrahiert werden muss, um die lokale Speicherung so zu gestalten

sub XXX, %rsp 

am Anfang jedes Funktionsaufrufs, auch wenn es sich nicht um Blattfunktionen handelt. Häufig kann der vom Compiler ausgegebene Code den temporären Platz in der roten Zone unter dem Stapelzeiger verwenden, ohne dass er gespeichert werden muss und bevor andere Funktionen aufgerufen werden. Dies ist eine nützliche Optimierung.

Wenn Sie den Stapelzeiger nicht mehr übergeben müssen, kann der ausgegebene Code rsp als Basiszeiger verwenden, einen Job, der normalerweise für rbp reserviert ist, und der ausgegebene Code kann rbp als ein anderes Universalregister verwenden.

Dies bedeutet letztendlich, dass der Prolog und der Epilog jedes Funktionsaufrufs zwei Anweisungen speichern können, die rbp speichern und wiederherstellen würden:

(Gnu Assembler)

pushq %rbp       # prologue [ two instructions not necessary ]
movq %rsp,%rbp

.... [code]

movq %rbp,%rsp   # epilogue [ two instructions not necessary ]
popq %rbp        

Beachten Sie, dass Sie in gcc das Flag -mno-red-zone übergeben können, wenn Sie es nicht möchten (aber das x86-64-ABI erfordert es). Der Linux-Kernel muss nicht ABI-konform sein und daher wird der gesamte Kernel-Code mit -mno-red-zone kompiliert.

Darüber hinaus ist der Zugriff auf den Speicher über den Stapelzeiger hinaus nicht gefährlich, wenn dies der erwartete Betriebsmodus ist. Es ist nur gefährlich und kann zu Korruption führen, wenn es ungeplant und unerwartet ist. Wenn der ausgegebene Code dies tut, weiß er, was er tut.

Brian Onn
quelle
Ja, ich verstehe das. Aber ist das Speichern von 1 Anweisung (Unteranweisung von esp) wirklich eine Optimierung? Ich meine, es sieht seltsam aus, wenn man ein paar Bytes und einen Prozessortakt spart, um die tatsächliche Möglichkeit der Datenkorruption in Kauf zu nehmen. Vielleicht gibt es dafür noch andere Gründe?
Alexander Dzyoba
3
Es ist nicht wirklich der Unter von esp , dass die Optimierung, aber da Sie nicht mehr haben Unter von esp, können Sie besonders als Basiszeiger verwenden ( in der Regel durch EBP getan) und die Verwendung EBP für etwas anderes in dem Funktionscode. Schließlich kann der Code, da esp jetzt der Basiszeiger ist, das Speichern und Wiederherstellen von ebp im Prolog / Epilog vermeiden. Ich werde die Antwort mit diesen zusätzlichen Informationen klären
Brian Onn
editieren und in rbp / rsp anstatt in ebp / esp ändern, da die rote Zone nur ein Teil des x86-64-ABI ist (obwohl nichts daran hindert, dass man dieselbe Technik mit 32-Bit-Registern anwendet; aber kein Compiler macht dies heute so)
Brian Onn
1
Das Weglassen von Frame-Zeigern hat überhaupt nichts mit der roten Zone zu tun - der Compiler kann den Stack indizieren, indem er ihn %rspin beide Richtungen als Basiszeiger verwendet.
Alecov