質問: x64では32ビット整数と64ビット整数の演算はどちらが高速? のページで Sayuriさんの回答のコメントでEgtraさんが > > x86/x86-64の32/64ビットモードでは、16ビット演算も、やはり32ビット命令より1バイト多く必要になります(オペランドサイズプリフィックス)。 > > > とコメントしていたのですが、 オペランドプリフィクスというのを知らなかったので調べた所、 このようなページが出てきました。 このページの下部の方に > > ここで気が付くのは、同じ命令でも、違うコードが出ている。 > > 例えば、 mov (%esi), %eax は > > > 16bitでは、67668B06 > > 32bitでは、8B06 > > 64bitでは、678B06 となっている。 > > > 67というのは、アドレスサイズプレフィックス 66というのは、オペランドサイズプレフィックス > > > (省略) > > > 16bitモードでは、アドレスサイズ、オペランドサイズが16bitが基本。 67を付けるとアドレスサイズが32bitになる。 > > 66を付けるとオペランドサイズが32bitになる。 > > > 32bitモードでは、アドレスサイズ、オペランドサイズが32bitが基本。 67を付けるとアドレスサイズが16bitになる。 > > 66を付けるとオペランドサイズが16bitになる。 > > > 64bitモードでは、アドレスサイズ64bit、オペランドサイズ32bitが基本。 67を付けるとアドレスサイズが16bitになる。 > > 66を付けるとオペランドサイズが16bitになる。 48を付けるとオペランドサイズが64bitになる。 > > > と書いてあり、ここでようやく1バイト増えるの意味が分かり、 「なるほど。64bitのプロセッサーでは16bit演算や64bit演算をする場合には、 同じ命令でも66や48などのプリフィクスを付けるため、命令自体のサイズが1バイト増え、非効率になると言っていたのか」 となんとなく納得したのは良いものの、 そもそものオペランドサイズ、アドレスサイズというのが私の理解で合っているのか分かりません。 (そもそも上の鍵括弧内もあっているか怪しいですが) --- オペランドサイズはそのまま「被演算子となるデータ型のサイズ」の事をオペランドサイズと呼んでいるという事で良いのでしょうか? もし、そうであるならば、16ビットモードの時代は、2**32以上の符号無し整数を扱う方法は無かったのでしょうか? また、64ビットモードの場合などで、わざわざ命令のサイズを増やしてまで、 オペランドサイズを16bitにする意味はあるのでしょうか? それとも、命令のサイズを増やしても演算スピードが速くなる事はあるのですか? わざわざshort、byteを使う場面というのはあるのですか? --- アドレスサイズは、割り当てられるアドレスの数で、例えば32ビットOSならば、2**32しかアドレスを割り振れないから、 4GBまでしかメモリを認識しなかった。 この理解であっているのでしょうか? この理解であっている場合、64ビットOSでは2**64のアドレスを扱う事ができるはずですが、 実際にはOSごとに扱えるメモリサイズは限られていると思います。 この場合、2**64で振られるアドレスの内、上位のビットはアドレスとして使わないという事になるのでしょうか? それとも、OSごとにアドレスサイズを変えているのでしょうか? (それだと、上の話のアドレスサイズ64bitが基本というのと合わない気がするので、これは多分違うとは思っている) また、これもオペランドサイズの時と同じ質問ですが、 わざわざ命令のサイズを大きくしてまで、アドレスサイズを16bitに縮小する意味があるのでしょうか? それとも、命令のサイズを増やしても演算スピードが速くなる事はあるのですか?
回答: > > 「なるほど。64bitのプロセッサーでは16bit演算や64bit演算をする場合には、 > > 同じ命令でも66や48などのプリフィクスを付けるため、命令自体のサイズが1バイト増え、非効率になると言っていたのか」 > > > YESです。 > > もし、そうであるならば、16bitモードの時代は、2**32以上の符号無し整数を扱う方法は無かったのでしょうか? > > > x86プロセッサーは16bit → 32bit → 64bitと進化してきています。 16bitプロセッサーの時代にはそもそも32bitを扱えませんでした。32bitプロセッサーが登場し後方互換のためのプロセッサーモードの概念が登場したことが今回の話題の始まりとも言えます。 32bitプロセッサーを16bitモードで使用する際に32bit演算を有効化するものがオペランドサイズプレフィックスです。ですので、拡張したとしても32bitしか扱えないのは当然です。 > > また、64ビットモードの場合などで、わざわざ命令のサイズを増やしてまで、オペランドサイズを16bitにする意味はあるのでしょうか? > > それとも、命令のサイズを増やしても演算スピードが速くなる事はあるのですか? > > わざわざshort、byteを使う場面というのはあるのですか? > > > 見てわかると思いますがオペランドサイズプレフィックスはビットフラグとして機能しているので、対称性の観点でも用意されたのでしょう。またUTF-16など16bit処理需要があると判断されたのかもしれません。 プロセッサーの速度に影響する観点として重要度の高い順に並べると 1. 命令の取得 2. 命令が扱うデータの取得 3. 命令に沿った演算 となります。1.当たり前ですが命令を読み込まなければ何を実行するかわかりませんからもっとも重要度が高くなります。命令プレフィックスの1バイトが大きく影響するのもこのためです。2.実行すべき命令が決まってもデータが揃わなければ演算は行えません。データの取得は重要な観点です。大量のデータを扱う場合、冗長な命令プレフィックスを付けてでもデータサイズを削減することは意義があります。3.プロセッサーの本来の役目であるべき演算は技術の進歩でほとんど比重が低くなっています。 > > アドレスサイズは、割り当てられるアドレスの数で、例えば32ビットOSならば、2**32しかアドレスを割り振れないから、4GBまでしかメモリを認識しなかった。 > > > この理解であっている場合、64ビットOSでは2**64のアドレスを扱う事ができるはずですが、 > > 実際にはOSごとに扱えるメモリサイズは限られていると思います。 > > > 32bitプロセッサーから仮想記憶の概念が登場しています。OSはこの仮想記憶を使用してプロセスごとに独立したメモリ空間を提供することでセキュリティや信頼性を確保しています。(16bitプロセッサーではすべてのメモリが共有されていたため、他のプロセスやOS自体を変更・破壊することが可能でした。)この仮想記憶により、仮想的に扱えるメモリサイズと物理的に扱えるメモリサイズは関係がなくなりました。 物理的に扱えるメモリサイズは例えば16bitプロセッサーの時代から20bit扱えていたなど泥沼の歴史が出てきますので割愛します。 > > わざわざ命令のサイズを大きくしてまで、アドレスサイズを16bitに縮小する意味があるのでしょうか? > > > これはちょっとわかりません。個人的な体感としては64bit Windowsを使用していると32bit Windowsとの互換のためにアドレス情報を格納するのに32bit領域しか確保できないという場面も多々あり、そういった場合に32bitアドレッシングにも意味があるのかなと思ったり思わなかったりします。