wake-up-neo.com

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

In der x86-64 Tour of Intel Manuals habe ich gelesen

Die vielleicht überraschendste Tatsache ist, dass eine Anweisung wie MOV EAX, EBX löscht automatisch die oberen 32 Bits des Registers RAX.

In der Intel-Dokumentation (3.4.1.1 Allgemeine Register im 64-Bit-Modus in Manual Basic Architecture), die an derselben Quelle zitiert wird, heißt es:

  • 64-Bit-Operanden erzeugen ein 64-Bit-Ergebnis im Ziel-Universalregister.
  • 32-Bit-Operanden erzeugen ein 32-Bit-Ergebnis, das im Ziel-Universalregister auf ein 64-Bit-Ergebnis von Null erweitert wird.
  • 8-Bit- und 16-Bit-Operanden erzeugen ein 8-Bit- oder 16-Bit-Ergebnis. Die oberen 56 Bits bzw. 48 Bits des Ziel-Universalregisters werden durch die Operation nicht geändert. Wenn das Ergebnis einer 8-Bit- oder 16-Bit-Operation für die 64-Bit-Adressberechnung vorgesehen ist, erweitern Sie das Register explizit mit Vorzeichen auf die vollständigen 64-Bit-Adressen.

In x86-32- und x86-64-Assembly werden 16-Bit-Anweisungen wie z

mov ax, bx

zeige nicht diese Art von "seltsamem" Verhalten, dass das obere Wort von eax auf Null gesetzt ist.

Also: Was ist der Grund, warum dieses Verhalten eingeführt wurde? Auf den ersten Blick scheint es unlogisch (aber der Grund könnte sein, dass ich an die Macken der x86-32-Assembly gewöhnt bin).

94
Nubok

Ich bin nicht AMD oder spreche für sie, aber ich hätte es genauso gemacht. Da durch das Nullsetzen der oberen Hälfte keine Abhängigkeit vom vorherigen Wert entsteht, muss die CPU warten. Der Mechanismus zur Umbenennung von Registern würde im Wesentlichen zunichte gemacht, wenn dies nicht auf diese Weise geschehen würde. Auf diese Weise können Sie schnellen 32-Bit-Code im 64-Bit-Modus schreiben, ohne die Abhängigkeiten ständig explizit aufheben zu müssen. Ohne dieses Verhalten müsste jeder einzelne 32-Bit-Befehl im 64-Bit-Modus auf etwas warten, das zuvor passiert ist, obwohl dieser hohe Teil fast nie verwendet würde.

Das Verhalten bei 16-Bit-Befehlen ist seltsam. Der Abhängigkeits-Wahnsinn ist einer der Gründe, warum 16-Bit-Befehle jetzt vermieden werden.

79
harold

Es spart einfach Platz in den Anweisungen und im Anweisungssatz. Sie können kleine Sofortwerte in ein 64-Bit-Register verschieben, indem Sie vorhandene (32-Bit-) Anweisungen verwenden.

Außerdem müssen Sie keine 8-Byte-Werte für MOV RAX, 42 Codieren, wenn MOV EAX, 42 Wiederverwendet werden kann.

Diese Optimierung ist für 8- und 16-Bit-Operationen nicht so wichtig (weil sie kleiner sind), und das Ändern der Regeln würde auch alten Code beschädigen.

9
Bo Persson