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 AntwortenWie 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.