title: x86_64 registers rax/eax/ax/al overwriting full register contents
body: <p>As it is widely advertised, modern x86_64 processors have 64-bit registers that can be used in backward-compatible fashion as 32-bit registers, 16-bit registers and even 8-bit registers, for example:</p>
  
  <pre><code>0x1122334455667788
    ================ rax (64 bits)
            ======== eax (32 bits)
                ====  ax (16 bits)
                ==    ah (8 bits)
                  ==  al (8 bits)
  </code></pre>
  
  <p>Such a scheme may be taken literally, i.e. one can always access only the part of the register using a designated name for reading or writing purposes, and it would be highly logical. In fact, this is true for everything up to 32-bit:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>However, things seem to be fairly awkward as soon as we get to 64-bit stuff:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Such behavior seems to be highly ridiculous and illogical to me. It looks like trying to write anything at all to <code>eax</code> by any means leads to wiping of high 32 bits of <code>rax</code> register.</p>
  
  <p>So, I have 2 questions:</p>
  
  <ol>
  <li><p>I believe that this awkward behavior must be documented somewhere, but I can't seem to find detailed explanation (of how exactly high 32 bits of 64-bit register get wiped) anywhere. Am I right that writing to <code>eax</code> always wipes <code>rax</code>, or it's something more complicated? Does it apply to all 64-bit registers, or there are some exceptions?</p>
  
  <p>A <a href="https://stackoverflow.com/questions/11822646/can-mov-eax-0x1-always-be-used-instead-of-mov-rax-0x1">strongly related question</a> mentions the same behavior, but, alas, there are again no exact references to documentation.</p>
  
  <p>In other words, I'd like a link to documentation that specifies this behavior.</p></li>
  <li><p>Is it just me or this whole thing seems to be really weird and illogical (i.e. eax-ax-ah-al, rax-ax-ah-al having one behavior and rax-eax having another)? May be I'm missing some kind of vital point here on why was it implemented like that?</p>
  
  <p>An explanation on "why" would be highly appreciated.</p></li>
  </ol>