Qual é o objetivo da zona vermelha?

12

Zona vermelha é uma área de tamanho fixo na memória além do ponteiro da pilha que não foi "alocado". Os compiladores geram montagem para acessar essa área em funções simples de folha.

Mas não vejo vantagens reais na zona vermelha. O acesso à memória além do ponteiro da pilha é realmente perigoso e pode facilmente levar à corrupção de dados . Por que fazer isso? Salvar duas instruções do processador (push ebp; mov ebp esp) não dará velocidade real.

Alexander Dzyoba
fonte

Respostas:

16

A zona vermelha é pura e simplesmente uma otimização que pode salvar instruções. Isso significa que não é mais necessário que o código emitido para cada função subtraia do ponteiro da pilha para tornar o armazenamento local assim

sub XXX, %rsp 

no início de cada chamada de função, mesmo que não sejam funções folha. Muitas vezes, o código emitido pelo compilador pode usar o espaço temporário na zona vermelha abaixo do ponteiro da pilha sem precisar salvá-lo e antes de chamar outras funções. Essa é uma otimização útil para ter disponível.

Se você não precisar mais usar o ponteiro da pilha, o código emitido poderá usar rsp como ponteiro base, um trabalho normalmente reservado para rbp, e o código emitido poderá usar rbp como outro registro de uso geral.

Isso significa que o prólogo e o epílogo de cada chamada de função podem salvar duas instruções que salvariam e restaurariam o rbp:

(montador gnu)

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

.... [code]

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

Observe que no gcc você pode passar o sinalizador -mno-red-zone se não quiser (mas a ABI x86-64 exige). O kernel do Linux não precisa ser compatível com ABI e, portanto, todo o código do kernel é compilado com -mno-red-zone.

Além disso, acessar a memória além do ponteiro da pilha não é perigoso se esse for o modo de operação esperado. É apenas perigoso e pode levar à corrupção quando não é planejado e inesperado. Quando o código emitido faz isso, ele sabe o que está fazendo.

Brian Onn
fonte
Sim, eu entendo isso. Mas salvar 1 instrução (sub de esp) é realmente otimização? Quero dizer, economizar alguns bytes e 1 ciclo do processador pelo preço da possibilidade real de corromper os dados parece estranho. Talvez haja outras razões para fazer isso?
Alexander Dzyoba
3
Não é realmente o sub do esp que é a otimização, mas como você não precisa mais sub do esp, você pode usar o esp como ponteiro base (normalmente feito pelo ebp) e o ebp para outra coisa no código de função. Por fim, como agora o esp é o ponteiro base, o código pode evitar salvar e restaurar o ebp no prólogo / epílogo. Esclarecerei a resposta com esta informação extra.
Brian Onn
edite e mude para rbp / rsp em vez de ebp / esp, pois a zona vermelha é apenas uma parte da ABI x86-64 (embora nada impeça alguém de usar a mesma técnica com registros de 32 bits; mas nenhum compilador faz isso hoje)
Brian Onn
1
A omissão do ponteiro de quadro não está relacionada à zona vermelha - o compilador pode indexar a pilha usando %rspcomo ponteiro base de qualquer maneira.
alecov 22/07/19