Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Toda a memória além do endereço atual do RSP é considerada volátil: o sistema operativo, ou um depurador, pode sobrescrever essa memória durante uma sessão de depuração do utilizador ou pela ação de um manipulador de interrupção. Assim, o RSP deve sempre ser configurado antes de tentar ler ou gravar valores em um quadro de stack.
Esta seção discute a alocação de espaço de pilha para variáveis locais e a alocação intrínseca.
Alocação de pilha
O prólogo de uma função é responsável por alocar espaço de pilha para variáveis locais, registros salvos, parâmetros de pilha e parâmetros de registro.
A área de parâmetros está sempre na parte inferior da pilha (mesmo quando alloca é usado), de modo que estará sempre adjacente ao endereço de retorno durante qualquer chamada de função. Ele contém pelo menos quatro entradas, mas sempre espaço suficiente para armazenar todos os parâmetros necessários para qualquer função que possa ser chamada. Observe que o espaço é sempre alocado para os parâmetros de registro, mesmo que os parâmetros em si nunca sejam hospedados na pilha; Um destinatário tem a garantia de que o espaço foi alocado para todos os seus parâmetros. Os endereços residenciais são necessários para os argumentos de registro, portanto, uma área contígua está disponível no caso de a função chamada precisar tomar o endereço da lista de argumentos (va_list) ou um argumento individual. Esta área também fornece um local conveniente para salvar argumentos de registo durante a execução do thunk e como uma opção de depuração (por exemplo, torna os argumentos fáceis de encontrar durante a depuração se eles estiverem armazenados nos seus endereços de origem no código do prólogo). Mesmo que a função chamada tenha menos de 4 parâmetros, esses 4 locais de pilha são efetivamente propriedade da função chamada e podem ser usados pela função chamada para outros fins além de salvar valores de registro de parâmetros. Assim, o chamador pode não conseguir salvar informações nessa região da pilha durante uma chamada de função.
Se o espaço é alocado dinamicamente (alloca) numa função, então um registo não volátil deve ser usado como um ponteiro de estrutura para indicar a base da parte fixa da pilha e esse registo deve ser salvo e inicializado no prólogo. Observe que, quando alloca é usado, as chamadas para o mesmo destinatário do mesmo chamador podem ter endereços residenciais diferentes para seus parâmetros de registro.
A pilha sempre será mantida alinhada com 16 bytes, exceto dentro do prolog (por exemplo, depois que o endereço de retorno é enviado) e exceto quando indicado em Tipos de função para uma determinada classe de funções de quadro.
A seguir está um exemplo do layout da pilha onde a função A chama uma função não-folha B. O prólogo da função A já alocou espaço para todos os parâmetros de registro e pilha exigidos por B na parte inferior da pilha. A chamada envia o endereço de retorno e o prolog de B aloca espaço para suas variáveis locais, registros não voláteis e o espaço necessário para chamar funções. Se B usa alloca, o espaço é alocado entre a variável local/área de salvamento de registro não volátil e a área da pilha de parâmetros.
Quando a função B chama outra função, o endereço de retorno é colocado logo abaixo do endereço inicial do RCX.
Construção de área de pilha de parâmetros dinâmicos
Se um ponteiro de quadro for usado, há a opção de criar dinamicamente a área da pilha de parâmetros. Isso não é feito atualmente no compilador x64.
Tipos de funções
Existem basicamente dois tipos de funções. Uma função que requer um quadro de pilha é chamada de função de quadro. Uma função que não requer um quadro de pilha é chamada de função folha.
Uma função de enquadramento é uma função que aloca espaço de pilha, chama outras funções, salva registos não voláteis ou utiliza tratamento de exceções. Também requer uma entrada de tabela de funções. Uma função de quadro requer um prólogo e um epílogo. Uma função de quadro pode alocar dinamicamente espaço de pilha e pode empregar um ponteiro de quadro. Uma função de frame tem todas as capacidades completas deste padrão de chamada ao seu dispor.
Se uma função de frame não chamar outra função, então não é necessário alinhar a pilha (referenciada na secção Alocação de Pilha).
Uma função folha é aquela que não requer uma entrada de tabela de funções. Ele não pode fazer alterações em nenhum registro não volátil, incluindo RSP, o que significa que ele não pode chamar nenhuma função ou alocar espaço de pilha. É permitido deixar a pilha desalinhada enquanto ela é executada.
Alinhamento Malloc
malloc garante retornar memória devidamente alinhada para armazenar qualquer objeto com um alinhamento fundamental e que caiba na memória alocada. Um alinhamento fundamental é um alinhamento menor ou igual ao maior alinhamento suportado pela implementação sem uma especificação de alinhamento. (No Microsoft C++, este é o alinhamento necessário para um double, ou 8 bytes. No código destinado a plataformas de 64 bits, são 16 bytes.) Por exemplo, uma alocação de quatro bytes seria alinhada em um limite que ofereça suporte a qualquer objeto de quatro bytes ou menor.
Visual C++ permite tipos que têm alinhamento estendido, que também são conhecidos como tipos sobrealinhados . Por exemplo, os tipos SSE __m128 e __m256, e os tipos que são declarados usando __declspec(align( n )) onde n é maior que 8, têm alinhamento estendido. O alinhamento de memória em um limite adequado para um objeto que requer alinhamento estendido não é garantido pelo malloc. Para alocar memória para tipos com sobrealinhamento, use _aligned_malloc e funções relacionadas.
Alloca
_alloca é necessário estar alinhado em 16 bytes e, adicionalmente, usar um ponteiro de quadro.
A pilha alocada precisa incluir espaço depois dela para parâmetros de funções subsequentemente chamadas, conforme discutido em Alocação de pilha.