Compartilhar via


Prólogo e Epilog

Cada função aloca espaço de pilha, chamadas de outras funções, salva os registros não-volátil ou usa o tratamento de exceção devem ter o prólogo cujos limites de endereço são descritas nos dados de desenrolamento associados à entrada de tabela respectiva função (consulte Tratamento (x64) de exceção). O prólogo salva argumento registradores em seus endereços residenciais se necessário, envia os registros não-volátil na pilha, aloca a parte fixa da pilha para locals e temporaries e, opcionalmente, estabelece um ponteiro de quadro. Dados de desenrolar o associado deve descrever a ação de prólogo e forneça as informações necessárias para desfazer o efeito do código de prólogo.

Se a alocação fixa na pilha é a mais de uma página (ou seja, maior que 4096 bytes), em seguida, é possível que a alocação de pilha poderia abranger mais de uma página de memória virtual e, portanto, a alocação deve ser verificada antes que ele é realmente alocado. Uma rotina especial que pode ser chamada do prólogo e que não destrói qualquer um dos registradores de argumento é fornecida para essa finalidade.

O método preferido para salvar os registros não-volátil é movê-los para a pilha antes que a alocação de pilha fixa. Se a alocação de pilha fixa foram realizada antes dos registradores de não-volátil foram salvos, então provavelmente seria um deslocamento de 32 bits necessário para o endereço de área (supostamente, verificações extras de registradores são apenas tão rápidas como movimentações e isso devem permanecer no futuro próximo, apesar da dependência implícita entre coloca) registra a salvo. Registradores de não-volátil podem ser salvo em qualquer ordem. No entanto, deve ser a primeira utilização de um registrador de não-volátil no prólogo para salvá-lo.

O código de prólogo típico pode ser:

mov       [RSP + 8], RCX
push   R15
push   R14
push   R13
sub      RSP, fixed-allocation-size
lea      R13, 128[RSP]
...

Este prólogo armazena o registro de argumento RCX em seu local de residência, não-volátil de salvamentos registra R13 R15, aloca a parte fixa do quadro de pilha e estabelece um ponteiro de quadro aponta 128 bytes para a área de alocação fixa. Um deslocamento permite que mais da área de alocação fixa sejam resolvidos com deslocamentos de um byte.

Se o tamanho de alocação fixa for maior ou igual a uma página de memória, uma função auxiliar deve ser chamada antes de modificar o RSP. Esse auxiliar, __chkstk, é responsável pela investigação do intervalo de pilha ser alocado, para garantir que a pilha é estendida adequadamente. Nesse caso, o exemplo de prólogo anterior em vez disso seria:

mov       [RSP + 8], RCX
push   R15
push   R14
push   R13
mov      RAX,  fixed-allocation-size
call   __chkstk
sub      RSP, RAX
lea      R13, 128[RSP]
...

O auxiliar de __chkstk não modificará os registradores diferente R10, R11 e os códigos de condição. Em particular, ele retornar RAX inalterado e deixe os registros de todos os não-volátil e registradores de passagem de argumento não modificados.

O código de epilog existe em cada sair para uma função. Enquanto houver normalmente apenas um prólogo, pode haver muitos epilogs. O código de epilog apara a pilha de seu tamanho de alocação fixa (se necessário), desaloca a alocação de pilha fixa, restaura o não-volátil registradores popping seus valores salvos da pilha e retorna.

O código de epilog deve seguir um conjunto estrito de regras para o código de desenrolamento para confiável desenrolamento por meio de exceções e interrupções. Isso reduz a quantidade de desenrolamento dados necessários, porque nenhum dado adicional é necessária para descrever cada epilog. Em vez disso, o código de desenrolamento pode determinar que uma epilog está sendo executada pela verificação de frente por meio de um fluxo de código para identificar um epilog.

Se nenhum ponteiro de quadro é usado na função, em seguida, o epilog deve primeiro desalocar a parte fixa da pilha, os registradores de não-volátil são exibidos e controle é devolvido à função de chamada. For example,

add      RSP, fixed-allocation-size
pop      R13
pop      R14
pop      R15
ret

Se o ponteiro do quadro é usado na função, a pilha deve ser aparada à sua alocação fixa antes para a execução do epilog. Isso é tecnicamente não faz parte do epilog. Por exemplo, o seguinte epilog pode ser usado para desfazer o prólogo usado anteriormente:

lea      RSP, -128[R13]
; epilogue proper starts here
add      RSP, fixed-allocation-size
pop      R13
pop      R14
pop      R15
ret

Na prática, quando o ponteiro do quadro é usado, não há nenhuma bom motivo para ajustar o RSP em duas etapas, portanto, a seguinte epilog seria usado em vez disso:

lea      RSP, fixed-allocation-size – 128[R13]
pop      R13
pop      R14
pop      R15
ret

Esses são os formulários legais apenas de um epilog. Ele deve consistir em um add RSP,constant ou lea RSP,constant[FPReg], seguido por uma série de zero ou mais pops de registrador de 8 bytes e um retorno ou jmp. (Somente um subconjunto de instruções de jmp são permitidas a epilog. Esses são exclusivamente da classe de jmps com ModRM referências de memória onde o campo mod de ModRM valor 00. É proibido o uso de jmps em que o epilog com o valor do campo mod ModRM 01 ou 10. Consulte a tabela-15 na AMD x Manual de volumes 86 64 arquitetura Programmer 3: Finalidade geral e instruções do sistema para obter mais informações sobre as referências de ModRM permitidas.). Nenhum outro código pode ser exibida. Em particular, nada pode ser agendado dentro de um epilog, incluindo o carregamento de um valor de retorno.

Observe que, quando o ponteiro do quadro não for usado, deve usar ao epilog add RSP,constant para desalocar a parte fixa da pilha. Ele não poderá usar lea RSP,constant[RSP] em vez disso. Essa restrição existe para que o código de desenrolamento tem menos de padrões para reconhecer quando estiver procurando epilogs.

Seguindo essas regras permite que o código de desenrolamento para determinar que uma epilog está atualmente sendo executada e simular a execução do restante do epilog para permitir a recriar o contexto da chamada de função.

Consulte também

Referência

x 64 convenções de Software