Prolog e Epilog
Cada função que aloca espaço de pilha, chama Outros funções, registradores de não-volátil salva ou usa o tratamento de exceção deve ter um prólogo cujos limites de endereço são descritos em dados desenrolamento associados a respectiva função entrada da tabela (consulte Exceção Handling (x64)). O prólogo salva argumento registradores em seus endereços base se necessário, empurra registros não-volátil na pilha, aloca a parte fixa da pilha para locais e temporaries e opcionalmente estabelece um ponteiro de quadro.Dados desenrolar o associado deve descrever a ação de prólogo e deve fornecer as informações necessárias para desfazer o efeito do código de prólogo.
Se a alocação fixa da pilha é mais de uma página (isto é, maior que 4096 bytes), em seguida, é possível que a alocação da pilha poderia abranger mais de uma página de memória virtual e, portanto, a alocação deve ser verificada antes que ela é realmente alocada.Uma rotina especial que pode ser chamada do prólogo e que não destrói qualquer um dos registros argumento é fornecida para essa finalidade.
O método preferido para salvar registros não-volátil é para movê-los na pilha antes da alocação de pilha fixa.Se a alocação da pilha fixa foram executada antes dos registros não-volátil foram salvos, e em seguida, é mais provável um deslocamento de 32 bit seriam necessário para endereço a salvo registra área (supostamente, coloca de registradores é apenas tão rápida quanto movimentações e deve permanecer isso para o futuro previsível apesar da dependência implícita entre coloca).Registros não-volátil podem ser salvo em qualquer ordem.No entanto, deve ser o primeiro uso de um registrador 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 argumento registrador RCX em seu local de residência, salva não-volátil registra R13 R15, aloca a parte fixa do registro de ativação e estabelece um ponteiro de quadro que aponta 128 bytes para a área de alocação fixa.O uso de um deslocamento permite que mais da área de alocação fixa sejam resolvidos com deslocamentos de um byte.
Se o dimensionar de alocação fixa for maior que 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 __chkstk não modificará os registros sejam R10, R11 e os códigos de condição.Em particular, ele irá retornar RAX inalterada e deixe registra todos os não-volátil e registradores de passagem de argumento não modificados.
Epilog código existe em cada sair para uma função.Enquanto houver normalmente apenas um prólogo, pode haver muitos epilogs.Código epilog apara o conjunto de seu dimensionar de alocação fixa (se necessário), desaloca a alocação da pilha fixa, restaura registros não-volátil, exibir os valores salvos da pilha e retorna.
O código epilog deve seguir um conjunto estrito de regras para o código de desenrolamento para desenrolamento confiável por meio de exceções e interrupções.Isso reduz a quantidade de dados necessários, de desenrolamento porque nenhum dado adicional é necessária para descrever cada epilog.Em vez disso, o código de desenrolamento pode determinar que um epilog está sendo executado verificando encaminhar através de um fluxo de código para identificar um epilog.
Se nenhum ponteiro de quadro é usado na função e, em seguida, o epilog deve primeiro desalocar a parte fixa da pilha, os registros não-volátil estão exibidos e controle é devolvido para a função de chamada.Por exemplo,
add RSP, fixed-allocation-size
pop R13
pop R14
pop R15
ret
Se um ponteiro de quadro for usado na função, a pilha deve ser aparada para sua alocação fixa antes para a execução do epilog.Isso é tecnicamente não parte de epilog.Por exemplo, epilog seguinte 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á nenhum um mercadoria motivo para ajustar o RSP em duas etapas, para que seria usado epilog seguinte:
lea RSP, fixed-allocation-size – 128[R13]
pop R13
pop R14
pop R15
ret
Esses são os formulários legais apenas para um epilog.Deve consistir de um um add RSP,constant ou lea RSP,constant[FPReg], seguido por uma série de zero ou mais registrador de 8 byte é exibida e uma devolução ou um jmp. (Apenas um subconjunto de instruções jmp são permitidos no epilog.Esses são exclusivamente da classe de jmps com referências de memória ModRM onde ModRM mod campo valor 00.O uso de jmps em epilog com valor do campo mod ModRM 01 ou 10 é proibido.Consulte A tabela-15 no AMD x86-64 arquitetura Programmer Manual Volume 3: Uso geral e instruções de sistema, para obter mais informações sobre as referências ModRM permitidas.).Nenhum Outros código poderá ser exibida.Em particular, nada pode ser agendado dentro de um epilog, incluindo o carregamento de um valor retornado.
Observe que, quando um ponteiro de quadro não for usado, o epilog deve usar add RSP,constant Para desalocar a parte fixa da pilha. Não pode usar lea RSP,constant[RSP] em vez disso. Essa restrição existe, portanto o código de desenrolamento tem menos padrões para reconhecer ao procurar epilogs.
Seguir essas regras permite que o código de desenrolamento para determinar um epilog atualmente está sendo executado e para simular a execução do restante epilog para permitir que recriar o contexto da função chamada.