Partilhar via


Usando e preservando registros em montagem em linha

Específico da Microsoft

Em geral, não se deve assumir que um registo terá um determinado valor quando um bloco __asm começa. Não é garantido que os valores de registro sejam preservados em blocos separados __asm . Se você terminar um bloco de código embutido e começar outro, não poderá confiar nos registradores no segundo bloco para reter seus valores do primeiro bloco. Um __asm bloco herda quaisquer valores de registro resultantes do fluxo normal de controle.

Se utilizar a __fastcall convenção de chamada, o compilador passa argumentos de função em registos em vez de na pilha. Isso pode criar problemas em funções com __asm blocos, porque uma função não tem como dizer qual parâmetro está em qual registro. Se a função receber um parâmetro no EAX e armazenar imediatamente outra coisa no EAX, o parâmetro original será perdido. Além disso, você deve preservar o registro ECX em qualquer função declarada com __fastcall.

Para evitar tais conflitos de registro, não use a __fastcall convenção para funções que contenham um __asm bloco. Se especificar a __fastcall convenção globalmente com a opção do compilador /Gr, declare cada função que contenha um bloco __asm com __cdecl ou __stdcall. (O __cdecl atributo diz ao compilador para usar a convenção de chamada C para essa função.) Se você não estiver compilando com /Gr, evite declarar a função com o __fastcall atributo.

Ao usar __asm para escrever linguagem assembly em funções C/C++, você não precisa preservar os registros EAX, EBX, ECX, EDX, ESI ou EDI. Por exemplo, no exemplo POWER2.C em Writing Functions with Inline Assembly, a power2 função não preserva o valor no registo EAX. No entanto, o uso desses registros afetará a qualidade do código porque o alocador de registro não pode usá-los para armazenar valores entre __asm blocos. Além disso, ao usar EBX, ESI ou EDI em código assembler embutido, força-se o compilador a salvar e restaurar esses registos no prólogo e epílogo da função.

Você deve preservar outros registos que utiliza (como DS, SS, SP, BP e registos de bandeiras) para o bloco __asm. Você deve preservar os registros ESP e EBP, a menos que tenha algum motivo para alterá-los (para alternar pilhas, por exemplo). Consulte também Otimizando a montagem em linha.

Alguns tipos de SSE exigem alinhamento de pilha de oito bytes, forçando o compilador a emitir código dinâmico de alinhamento de pilha. Para poder acessar as variáveis locais e os parâmetros de função após o alinhamento, o compilador mantém dois ponteiros de quadro. Se o compilador executar omissão de ponteiro de quadro (FPO), ele usará EBP e ESP. Se o compilador não executar FPO, ele usará EBX e EBP. Para garantir que o código seja executado corretamente, não modifique o EBX no código asm se a função exigir alinhamento dinâmico da pilha, pois pode modificar o ponteiro de enquadramento. Mova os tipos alinhados de oito bytes para fora da função ou evite usar o EBX.

Observação

Se o código de montagem embutido alterar o sinalizador de direção usando as instruções STD ou CLD, você deverá restaurar o sinalizador para seu valor original.

END Específico da Microsoft

Ver também

Montador em linha