CodeZine(コードジン)

特集ページ一覧

AMD64の特徴と機械語コーディング

Windows実行ファイル「EXE」の謎に迫る 第7回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/07/28 00:00

64ビットCPUが出始めて数年が経ち、多くのPCが64ビット化しつつあります。今回は、64ビット技術がどのような特徴を持ち合わせているのか、また、ソフトウェア側のアプローチをどのように進めていったらよいのかというテーマについて語ります。

目次

はじめに

 64ビットCPUが出始めて、数年が経ちます。現状では、ほとんどのデスクトップPCが64ビットCPUを搭載する形になり、ノートPCの64ビット化も時間の問題と思われます。今回は、64ビット技術がどのような特徴を持ち合わせているのか、ソフトウェア側のアプローチをどのように進めていったらよいのかという話題で進みます。

そもそも、64ビットCPUって

 実は、ひとことで64ビットCPUと言うと、2つの異なるCPUを意味してしまいます。

  • AMD64/EM64-T
  • IA-64

 AMD64/EM64-T(以下、AMD64)とは、x86アーキテクチャのレジスタ幅を64ビットに拡張し、64ビット対応のネイティブコードを追加した規格になります。一般的に、パソコン市場で64ビットCPUと言うと、ほとんどがこちらのAMD64のことを意味しています。因みに、このアーキテクチャの設計を一番初めに行ったのはAMDです。Intelは後追いの形でEM64-Tを発表し、双方のCPUには互換性があります。

 IA-64は、Intelが開発したCPUアーキテクチャです。128個の汎用レジスタ、高度なパイプライン処理などを特徴とし、CPUの機能としてはかなり高いレベルを保持しますが、AMD64と比較したときの価格や互換性、コンシューマへの浸透率などが問題視され、サーバーサイドへの供給に留まっています。

 今後、一般のユーザーに浸透していくと予想されるのはAMD64です。今回はx86からAMD64への拡張がいかなるものなのか、そこにはどのようなメリットが生じているのかを、機械語レベルで解説していきます。

64ビットの命名問題。ちょっとややこしい!?

 実は、AMD64と同じ意味で下記のような名前が利用されることがあります。これらは呼び名が異なるだけで、同等の意味を持っていると思ってもらって差し支えありません。本稿では「AMD64」という呼び名に統一させていただきますので、ご了承ください。

AMD64の別名一覧
呼び名説明
AMD64x86を64ビットに拡張したアーキテクチャを初めて公開した際に、AMDが命名。
IA-32eIA-32の64ビット拡張(Extension)版。基本設計はAMD64と同様。
EM64-TExtended Memory 64 Technologyの略。意味はIA-32eと同様。
x86-64x86を64ビット拡張しましたよ、という意味を持つ。
x64上記の名前が煩わしいので、これらの総称に用いる場合が多い(マイクロソフトはx64を多様しています)。

64ビットのメリット

 新しいアーキテクチャのCPUと言うと、処理速度向上というキーワードが頭に浮かびますが、今回の64ビット化は、それよりも大きなメリットがあります。それは仮想記憶容量が格段に増える点。64ビット化によるメリットはなんといってもこれにつきます。

テラバイト単位のデータが手軽に扱える

 従来の32ビットWindows環境との使用可能メモリの比較状況を表1に示します。

表1 使用可能メモリの比較
Windows XP (32ビット通常版)Windows XP Professional x64 Edition
最大物理メモリ4GB128GB
最大仮想メモリ4GB16TB
16ビットアプリ×
32ビットアプリ ○(
64ビットアプリ×

 どうやら、仮想メモリがテラバイト単位まで確保できる模様です。数ギガバイトのデータでビビっている筆者はこれだけで相当なインパクトを受けたわけですが、実は64ビット化による仮想メモリの用途があまり見出せていないという少々お粗末な現状があることも忘れてはいけません。大掛かりなグラフィックス処理やマルチメディア演算、大規模データを扱うCADやデータベースソフトなどでの活躍が見込まれていますが、筆者の率直な意見を述べますと、一般消費者に向けた技術革新が多少薄いような印象を受けてます。多分、ここらへんの一般層への浸透率に関する問題は、Windows Vistaが解消してくれるものだと信じたいところです。

 その反面、物理メモリの壁が4GBを突破する点は見逃せません。1GBの物理メモリが平気で流通してしまう世の中ですので、ソフトウェア側が4GB超を要求する日はそう遠くはなさそうです。

 どちらにせよ、64ビット化に伴う非常に大きなメリットの一つとして、その膨大なメモリ空間が挙げられるのは間違いありません。

注(表1)
 ※ドライバなど、特殊なアプリケーションを除く。

32ビットソフトウェアとの互換性が非常に高い

 先ほどの表1にも記載してあるとおり、64ビット版Windowsでは、ほとんどの32ビットアプリケーションが快適に動作します。さらに、AMD64アーキテクチャにはロングモード/レガシーモードという2つのモードが搭載され、OSを越えた互換性を提供しています。

  • ロングモード
  • 64ビット版のOSが動作するモードです。ネイティブな64ビットアプリケーションがCPUポテンシャル100%で実行されます。
  • レガシーモード
  • x86と完全互換のアーキテクチャをシミュレートするモードです。ハードウェア単位でモードが切り替わるため、x86に対応する32ビットOSが動作可能です。いったんこのモードで立ち上がったOS上では、残念ながら64ビットの恩恵を受けることはできません。

 この解説を読む限りだと、「32ビットのソフトウェアはロングモードで動くのか?」といった疑問が生まれますが、ご安心いただいて結構です。Windows XP Professional 64bit Editionには、WOW64(Windows on Windows 64)というソフトウェア的な機構が用意されており、OSが32ビットネイティブコードの実行の面倒を見てくれます(下図参照)。

WOW64の仕組み
WOW64の仕組み

 このように、ハードウェアから根こそぎ32ビットモード(レガシーモード)で動作させることも可能ですし、ロングモードで動作させたときでもWOW64が32ビットの実行環境を提供してくれています。

 ここまで互換性がしっかりしていると、Windows Vistaがリリースされることで、より一層、一般消費者の64ビット化が進みそうです。

x86とAMD64のアーキテクチャ的な相違点

 AMD64はx86をベースに64ビット拡張がなされたアーキテクチャですが、具体的にはどのような点に変更が生じているのでしょうか。

ビット数が増量

 x86では32ビットだったレジスタが、AMD64では64ビットに拡張されています。一つのレジスタで表現できるアドレス空間が、理論上、4GBから16EB(エクサバイト*1)までに広がりました(現段階ではソフトウェア的な都合上、16TBとまでとなっています)。

 x86の環境で64ビット整数演算を行う際は、一つの値を保持するだけでも2つのレジスタを必要としていました。AMD64では、64ビット整数・実数を単体レジスタで手軽に扱えるため、従来のx86環境と比較して高速に、64ビット演算を行うことができます。表2は8~64ビットの値が表現できる範囲を示しています。

表2 表現できる整数値の範囲
データ型ビット数符号あり符号なし
Char / Byte8-128 ~ 1270 ~ 255
Integer / Word16-32768 ~ 327670 ~ 65535
Long / DWord32-2147483648 ~ 21474836470 ~ 4294967295
Int64 / QWord64-9223372036854775808 ~ 92233720368547758070 ~ 18446744073709551615
編注)*1
 エクサ(E) …… 10の18乗を意味する接頭辞(ただし、2進数においては2の60乗)。

レジスタ本数が増量

 従来は8本だった汎用レジスタが、倍の16本に増えました。クロック周波数が格段に向上するわけではないx64展開ですが、これらの増量されたレジスタを、ソフトウェア側がどれだけ有効活用できるかで、実行速度は格段に向上するはずです。

 アセンブラ使いの方やコンパイラ開発者の方は、レジスタの64ビット化より、むしろこちらの方が興味深い拡張だったのかもしれません。いかにメモリアクセスを少なく、レジスタのみで処理をパスするのかは永遠の課題であり、ハードウェアに補助してもらいたい問題の一つでもあります。

SSE2を標準搭載

 x86までは、下位互換のため、FPU(実数演算のためのスタック構造64ビットレジスタ)に頼っていた部分があり、実数演算は遅いものだという認識がありました。

 これに対し、x64の水準を満たしているCPUは、すべてSSE2を備えています。ということは、x64に対応するソフトウェアは自動的にSSE2に対応するコードを生成できるということになります。

 SSE2を標準搭載したことに加え、xmm0~xmm7までの8個だったXMMレジスタの数がxmm0~xmm15までの16個に増加しました。汎用レジスタが16個に増えたのと同様の拡張であり、これもまた一部の技術者にとってはありがたい出来事です。

AMD64機械語の特性

 アセンブラ、機械語レベルでは、基本的な記述方法はx86のそれと対して変わりません。気をつけたいところは、拡張されたレジスタをどのように表現するのか、SSE2に完全移行される浮動小数演算をどのような流れで実現すべきなのかにあります(SSE2に関しての解説は、次回に持ち越します)。

幅・個数共に増幅したレジスタの表現

 先ほど説明したとおり、AMD64は64ビットを表現できる16個の汎用レジスタを搭載しています。アセンブラ、機械語レベルでそれらの汎用レジスタに自由にアクセスする必要があります。まず、アセンブラでは下記のような汎用レジスタの記述が可能です。

表1 AMD64の汎用レジスタ
32ビット64ビット備考
eaxrax汎用レジスタ
ecxrcx
edxrdx
ebxrbx
esprspスタックポインタ
ebprbpベースレジスタ
esirsiソース インデックス レジスタ
edirdiデスティネーション インデックス レジスタ
r8dr8拡張汎用レジスタ
r9dr9
r10dr10
r11dr11
r12dr12
r13dr13
r14dr14
r15dr15

 この表を見れば一目瞭然ですが、64ビット幅を持つレジスタはraxrcxのように「r」が先頭文字として存在し、r8r15のレジスタが拡張されています。rsprbpのような特殊な用途を持ち合わせるレジスタはr8r15にはありませんので、これらの拡張レジスタは比較的自由に扱うことができます。

REXプリフィックス

 さて、前々回の『x86系CPUのネイティブコードを解析する』で解説したレジスタを識別するための3ビットの内容を覚えておられるでしょうか。3ビットあれば、eaxesiの8個のレジスタを識別できるのは明白ですが、AMD64ではそれが16個に拡張されているのです。となると、レジスタを識別するために、x86よりも1ビット余分な4ビット分のデータ領域が必要となります。

 だからといって単純にレジスタ識別コード部分を4ビットに拡張するわけにはいきません。なぜなら、レジスタ識別の部分のみのビットを拡張することで、一つの命令語が1バイトで割り切れなくなるためです。

 そこで登場するのがREX(Register Extension)プリフィックス。名前の通り、拡張レジスタを表現するためのプリフィックスです。

 一般的なプリフィックスと同様、REXプリフィックスは1バイトの領域を使用し、具体的には下記のような状態判別を指定できます。

  • r/m、baseにr8r15のレジスタを使う
  • reg にr8r15のレジスタを使う
  • 64ビットオペランドとしてレジスタを指定する

 ようは、「従来のレジスタ識別のための3ビットがr8~r15までの拡張されたレジスタを示していますよ」または「指定したレジスタを64ビットとして扱ってくださいね」という意味付けを行えるのがREXプリフィックスということになります。ちなみに、REXプリフィックスとして指定可能なデータ範囲は0x40~0x4Fまでの16種類になります。下位4ビットはそれぞれ下記のような意味を持ちます。

  • 第0ビット … r/m、baseに拡張レジスタ(r8r15)を指定
  • 第1ビット … indexフィールドに拡張レジスタ(r8r15)を指定
  • 第2ビット … ModR/Mのregフィールドに拡張レジスタ(r8r15)を指定
  • 第3ビット … 64ビットオペランドの指定

 このREXプリフィックスを機械語の中に埋め込めれば、自動的に従来のネイティブコードフォーマットと高い互換性を保ちながら、拡張されたレジスタを大いに活用できる状況が生まれるワケです。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

バックナンバー

連載:Windows実行ファイル「EXE」の謎に迫る

もっと読む

All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5