の中にx86-64 インテル マニュアルのツアー、 私は読む
おそらく最も驚くべき事実は、 などの命令によりレジスタ
MOV EAX, EBX
の上位 32 ビットが自動的にゼロにされることです。RAX
同じソースで引用されている Intel のドキュメント (マニュアル「Basic Architecture」の「3.4.1.1 General-Purpose Registers in 64-Bit Mode」) には、次のように書かれています。
- 64 ビットのオペランドは、宛先汎用レジスタに 64 ビットの結果を生成します。
- 32 ビットのオペランドは 32 ビットの結果を生成し、宛先汎用レジスタで 64 ビットの結果にゼロ拡張されます。
- 8 ビットおよび 16 ビットのオペランドは、8 ビットまたは 16 ビットの結果を生成します。宛先汎用レジスタの上位 56 ビットまたは 48 ビット (それぞれ) は、演算によって変更されません。8 ビットまたは 16 ビットの演算結果が 64 ビットのアドレス計算に使用される場合は、レジスタを明示的に 64 ビット全体に符号拡張します。
x86-32およびx86-64アセンブリでは、16ビット命令、例えば
mov ax, bx
eax の上位ワードがゼロになるという、このような「奇妙な」動作は示されません。
では、この動作が導入された理由は何でしょうか? 一見すると非論理的に思えます (ただし、その理由は、私が x86-32 アセンブリの癖に慣れているからかもしれません)。
ベストアンサー1
私はAMDの人間ではないし、彼らの代わりに話しているわけでもないが、私なら同じ方法でやっただろう。なぜなら、上位半分をゼロにすることで、CPUが待つ前の値への依存が生じないからだ。レジスタ名の変更そうしないと、このメカニズムは本質的に無効になってしまいます。
この方法により、依存関係を常に明示的に解除することなく、64 ビット モードで 32 ビット値を使用して高速なコードを作成できます。この動作がなければ、64 ビット モードのすべての 32 ビット命令は、その上位部分がほとんど使用されなくても、以前に発生した何かを待機する必要があります。(64 ビットにすると、int
キャッシュ フットプリントとメモリ帯域幅が無駄になります。x86-64は32ビットと64ビットのオペランドサイズを最も効率的にサポートします)
8 ビットおよび 16 ビットのオペランド サイズの動作は奇妙です。依存関係の狂気は、現在 16 ビット命令が避けられている理由の 1 つです。x86-64 は、8 ビットの場合は 8086、16 ビットの場合は 386 からこれを継承し、8 ビットおよび 16 ビットのレジスタが 64 ビット モードでも 32 ビット モードと同じように動作するように決定しました。
参照GCC はなぜ部分レジスタを使用しないのですか?8 ビットおよび 16 ビットの部分レジスタへの書き込み (およびそれに続く完全なレジスタの読み取り) が実際の CPU によってどのように処理されるかについての実際的な詳細については、を参照してください。