x86_64-Register rax / eax / ax / al Überschreiben des vollständigen Registerinhalts [duplizieren]

Diese Frage hat hier bereits eine Antwort:

Warum setzen x86-64-Befehle in 32-Bit-Registern den oberen Teil des vollständigen 64-Bit-Registers auf Null? 2 Antworten

Wie weit verbreitet, verfügen moderne x86_64-Prozessoren über 64-Bit-Register, die abwärtskompatibel als 32-Bit-Register, 16-Bit-Register und sogar als 8-Bit-Register verwendet werden können. Beispiel:

0x1122334455667788
  ================ rax (64 bits)
          ======== eax (32 bits)
              ====  ax (16 bits)
              ==    ah (8 bits)
                ==  al (8 bits)

in solches Schema kann wörtlich genommen werden, d. H. Man kann immer nur auf den Teil des Registers zugreifen, indem ein bestimmter Name zum Lesen oder Schreiben verwendet wird, und es wäre sehr logisch. Tatsächlich gilt dies für alle bis zu 32-Bit-Versionen:

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)

Allerdings scheinen die Dinge ziemlich umständlich zu sein, sobald wir zu 64-Bit-Sachen kommen:

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

Solches Verhalten scheint mir höchst lächerlich und unlogisch zu sein. Es sieht so aus, als würde man versuchen, irgendetwas an @ zu schreibeeax führt auf jeden Fall zum Löschen von hohen 32 Bits vonrax registrieren

Also, ich habe 2 Fragen:

Ich glaube, dass dieses umständliche Verhalten irgendwo dokumentiert werden muss, aber ich kann anscheinend keine detaillierte Erklärung finden (wie genau 32 Bit des 64-Bit-Registers gelöscht werden). Habe ich recht, dass ich an @ schreibeax wischt immerrax, oder ist es etwas komplizierter? Gilt das für alle 64-Bit-Register, oder gibt es einige Ausnahmen?

A stark verwandte Frage erwähnt dasselbe Verhalten, aber leider gibt es auch hier keine genauen Verweise auf die Dokumentation.

it anderen Worten, ich hätte gerne einen Link zu einer Dokumentation, die dieses Verhalten beschreibt.

Ist es nur ich oder scheint diese ganze Sache wirklich seltsam und unlogisch zu sein (d. H. Eax-ax-ah-al, rax-ax-ah-al mit einem Verhalten und rax-eax mit einem anderen)? Vielleicht fehlt mir hier ein wichtiger Punkt, warum es so implementiert wurde?

Eine Erklärung zum "Warum" wäre sehr dankbar.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage