No Tour do x86-64 dos manuais da Intel , li
Talvez o fato mais surpreendente seja que uma instrução como essa
MOV EAX, EBX
zera automaticamente os 32 bits superiores doRAX
registro.
A documentação da Intel (3.4.1.1 Registros de uso geral no modo de 64 bits no manual Arquitetura básica) citada na mesma fonte nos diz:
- Operandos de 64 bits geram um resultado de 64 bits no registrador de uso geral de destino.
- Operandos de 32 bits geram um resultado de 32 bits, estendido por zero para um resultado de 64 bits no registrador de uso geral de destino.
- Operandos de 8 e 16 bits geram um resultado de 8 ou 16 bits. Os 56 bits ou 48 bits superiores (respectivamente) do registrador de uso geral de destino não são modificados pela operação. Se o resultado de uma operação de 8 ou 16 bits se destinar ao cálculo do endereço de 64 bits, estenda explicitamente o registro para 64 bits completos.
Em montagem x86-32 e x86-64, instruções de 16 bits, como
mov ax, bx
não mostre esse tipo de comportamento "estranho" de que a palavra superior de eax seja zerada.
Assim: qual é o motivo pelo qual esse comportamento foi introduzido? À primeira vista, parece ilógico (mas o motivo pode ser que estou acostumado com as peculiaridades do assembly x86-32).
r32
operando de destino zeram o 32 alto, em vez de mesclar. Por exemplo, alguns montadores substituirão pmovmskb r64, xmm
por pmovmskb r32, xmm
, salvando um REX, porque a versão de destino de 64 bits se comporta de forma idêntica. Embora a seção Operação do manual liste todas as 6 combinações de 32/64 bits dest e 64/128 / 256b fonte separadamente, a extensão zero implícita da forma r32 duplica a extensão zero explícita da forma r64. Estou curioso sobre a implementação do HW ...
xor eax,eax
ou xor r8d,r8d
é a melhor maneira de zerar RAX ou R8 (salvar um prefixo REX para RAX, e XOR de 64 bits não é nem tratado especialmente no Silvermont). Relacionado: Como exatamente os registros parciais no Haswell / Skylake funcionam? A escrita AL parece ter uma falsa dependência de RAX e AH é inconsistente