x86-64 Intelマニュアルのツアー で、私は読んだ
おそらく最も驚くべき事実は、
MOV EAX, EBX
は、RAX
レジスタの上位32ビットを自動的にゼロにします。
同じソースで引用されているインテルのドキュメント(マニュアルの基本アーキテクチャの64ビットモードでの3.4.1.1汎用レジスター)は、次のことを示しています。
- 64ビットオペランドは、デスティネーション汎用レジスタに64ビットの結果を生成します。
- 32ビットのオペランドは、デスティネーション汎用レジスタで64ビットの結果にゼロ拡張された32ビットの結果を生成します。
- 8ビットおよび16ビットのオペランドは、8ビットまたは16ビットの結果を生成します。デスティネーション汎用レジスタの上位56ビットまたは48ビット(それぞれ)は、操作によって変更されません。 8ビットまたは16ビット演算の結果が64ビットのアドレス計算を目的としている場合、レジスタを完全な64ビットに明示的に符号拡張します。
X86-32およびx86-64アセンブリでは、次のような16ビット命令
mov ax, bx
上のWord of eaxがゼロになるという、この種の「奇妙な」動作を見せないでください。
したがって、この動作が導入された理由は何ですか?一見、それは非論理的に思えます(しかし、その理由は、x86-32アセンブリの癖に慣れているからかもしれません)。
私はAMDではありませんし、彼らのために話しているわけでもありませんが、私はそれを同じようにしたでしょう。上位半分をゼロにしても以前の値への依存関係が作成されないため、CPUは待機する必要があります。レジスタ名変更メカニズムは、そうしないと本質的に無効になります。これにより、常に依存関係を明示的に解除することなく、64ビットモードで高速の32ビットコードを記述できます。この動作がなければ、64ビットモードのすべての32ビット命令は、その上位部分がほとんど使用されない場合でも、以前に発生した何かを待つ必要があります。
16ビット命令の動作は奇妙なものです。依存関係の狂気は、16ビット命令が現在回避されている理由の1つです。
命令と命令セットのスペースを節約するだけです。既存の(32ビット)命令を使用して、小さな即値を64ビットレジスタに移動できます。
また、MOV RAX, 42
を再利用できる場合、MOV EAX, 42
の8バイト値をエンコードする必要がなくなります。
この最適化は、8ビットと16ビットの操作ではそれほど重要ではありません(より小さいため)。そこでルールを変更すると、古いコードも破損します。