À quoi sert la zone rouge?

12

La zone rouge est une zone de taille fixe en mémoire au-delà du pointeur de pile qui n'a pas été "allouée". Les compilateurs génèrent un assemblage pour accéder à cette zone dans de simples fonctions de feuille.

Mais je ne vois aucun avantage réel pour la zone rouge. L'accès à la mémoire au-delà du pointeur de pile est vraiment dangereux et peut facilement entraîner une corruption des données . Pourquoi même faire ça? L'enregistrement de 2 instructions de processeur (push ebp; mov ebp esp) n'accélérera pas vraiment.

Alexander Dzyoba
la source

Réponses:

16

La zone rouge est, purement et simplement, une optimisation qui peut enregistrer des instructions. Cela signifie qu'il n'est plus nécessaire que le code émis pour chaque fonction soit soustrait du pointeur de pile pour rendre le stockage local comme tel

sub XXX, %rsp 

au début de chaque appel de fonction, même s'il ne s'agit pas de fonctions feuilles. Souvent, le code émis par le compilateur peut utiliser l'espace temporaire dans la zone rouge sous le pointeur de pile sans avoir besoin de l'enregistrer et avant d'appeler d'autres fonctions. Il s'agit d'une optimisation utile à mettre à disposition.

Si vous n'avez plus à vous soustraire du pointeur de pile, le code émis peut utiliser rsp comme pointeur de base, un travail normalement réservé à rbp, et le code émis peut utiliser rbp comme autre registre à usage général.

Cela signifie finalement que le prologue et l'épilogue de chaque appel de fonction peuvent enregistrer deux instructions qui enregistreraient et restaureraient rbp:

(assembleur gnu)

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

.... [code]

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

Notez que dans gcc, vous pouvez passer l'indicateur -mno-red-zone si vous ne le souhaitez pas (mais l'ABI x86-64 l'exige). Le noyau Linux n'a pas besoin d'être compatible ABI et donc tout le code du noyau est compilé avec -mno-red-zone.

De plus, l'accès à la mémoire au-delà du pointeur de pile n'est pas dangereux s'il s'agit du mode de fonctionnement attendu. C'est seulement dangereux et peut conduire à la corruption lorsqu'il n'est pas planifié et inattendu. Lorsque le code émis le fait, il sait ce qu'il fait.

Brian Onn
la source
Oui, je comprends cela. Mais est-ce que sauvegarder 1 instruction (sous esp) est vraiment une optimisation? Je veux dire économiser quelques octets et 1 cycle de processeur pour le prix d'une possibilité réelle de corruption de données semble étrange. Peut-être qu'il y a d'autres raisons pour cela?
Alexander Dzyoba
3
Ce n'est pas vraiment le sous-esp qui est l'optimisation, mais comme vous n'avez plus à sous-esp, vous pouvez utiliser esp comme pointeur de base (normalement fait par ebp) et utiliser ebp pour autre chose dans le code de fonction. Enfin, comme esp est désormais le pointeur de base, le code peut éviter d'enregistrer et de restaurer ebp dans le prologue / épilogue. Je vais clarifier la réponse avec ces informations supplémentaires
Brian Onn
modifier et changé en rbp / rsp au lieu de ebp / esp car la zone rouge n'est qu'une partie de l'ABI x86-64 (bien que rien n'empêche d'utiliser la même technique avec des registres 32 bits; mais aucun compilateur ne le fait de cette façon aujourd'hui)
Brian Onn
1
L'omission du pointeur de trame n'est pas du tout liée à la zone rouge - le compilateur peut indexer la pile en utilisant %rspcomme pointeur de base dans les deux cas.
alecov