x86 64 registos rax/eax/ax / al sobrescrever o conteúdo total do registo [duplicado]
0x1122334455667788
================ rax (64 bits)
======== eax (32 bits)
==== ax (16 bits)
== ah (8 bits)
== al (8 bits)
([9]} tal esquema pode ser tomado literalmente, isto é, pode-se sempre aceder apenas à parte do registo usando um nome designado para fins de leitura ou escrita, e seria altamente lógico. Na verdade, isso é verdade para tudo até 32 bits:
mov eax, 0x11112222 ; eax = 0x11112222
mov ax, 0x3333 ; eax = 0x11113333 (works, only low 16 bits changed)
mov al, 0x44 ; eax = 0x11113344 (works, only low 8 bits changed)
mov ah, 0x55 ; eax = 0x11115544 (works, only high 8 bits changed)
xor ah, ah ; eax = 0x11110044 (works, only high 8 bits cleared)
mov eax, 0x11112222 ; eax = 0x11112222
xor al, al ; eax = 0x11112200 (works, only low 8 bits cleared)
mov eax, 0x11112222 ; eax = 0x11112222
xor ax, ax ; eax = 0x11110000 (works, only low 16 bits cleared)
No entanto, as coisas parecem estranhas assim que chegamos a coisas de 64 bits.
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
mov eax, 0x55556666 ; actual: rax = 0x0000000055556666
; expected: rax = 0x1111222255556666
; upper 32 bits seem to be lost!
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
mov ax, 0x7777 ; rax = 0x1111222233337777 (works!)
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
xor eax, eax ; actual: rax = 0x0000000000000000
; expected: rax = 0x1111222200000000
; again, it wiped whole register
Esse comportamento parece - me muito ridículo e ilógico. Parece que estou a tentar escrever. qualquer coisa a eax
por qualquer meio leva a limpar de alto 32 bits de registro rax
.
Então, tenho duas perguntas:
-
Eu acredito que este comportamento estranho deve estar documentado em algum lugar, mas eu não consigo encontrar explicação detalhada (de como exatamente 32 bits de registro de 64 bits são apagados) em qualquer lugar. Tenho razão em escrever para apagar sempre, ou é algo mais complicado? Aplica-se a todos os registos de 64 bits, ou há alguns excepções?
a questão fortemente relacionada menciona o mesmo comportamento, mas, infelizmente, não há mais nenhuma referência exata à documentação.
Em outras palavras, Eu gostaria de um link para a documentação que especifica este comportamento. - É impressão minha ou tudo isto parece ser muito estranho e ilógico (ou seja, eax-AX-ah-al, rax-ax-ah-al ter um comportamento e rax-eax ter outro)? Talvez me esteja a escapar algum ponto vital sobre o porquê. implementado assim? Uma explicação sobre" porquê " seria muito apreciada.
1 answers
O modelo do processador documentado no manual do Processador Intel / AMD é um modelo bastante imperfeito para o Real motor de execução de um núcleo moderno. Em particular, a noção dos registros do processador não corresponde à realidade, não existe tal coisa como um registro EAX ou RAX.
Uma tarefa principal do descodificador de instruções é converter as instruções x86/x64 legadas em Micro-ops, Instruções de um processador RISC. Pequenas instruções que são fáceis de executar simultaneamente e ser capaz de tirar vantagem de várias subunidades de execução. Permitindo até 6 instruções para executar ao mesmo tempo.
Para fazer isso funcionar, a noção de registradores de processadores também é virtualizada. O descodificador de instruções atribui um registo de um grande banco de registos. Quando a instrução é aposentada, o valor desse registo dinamicamente atribuído é escrito de volta para qualquer registo que detém actualmente o valor de, digamos,, RAX.Para que isso funcione de forma suave e eficiente, permitindo que muitas instruções sejam executadas simultaneamente, é muito importante que estas operações não tenham uma interdependência. E o pior tipo que você pode ter é que o valor de registro depende de outras instruções. O registo de EFLAGS é notório, muitas instruções modificam-no.
O mesmo problema com a forma como tu gostas que funcione. Grande problema, ele requer dois valores de registro para ser fundido quando a instrução é Aposentado. Criar uma dependência de dados que vai entupir o núcleo. Ao forçar o 32-bit superior a 0, essa dependência desaparece instantaneamente, não mais uma necessidade de se fundir. Velocidade de execução Warp 9.