ホームに戻る
 64ビット研究

0、はじめに

64ビットのメリットといえば使用できるメモリの多さだと思う。
4GBを超える領域なんて必要無いという人も多いようだが、
扱うデータ量は肥大化する一方であるから先を見据える必要はあるだろう。
量に加えて、大量のプロセスを起動するなど数にも対応する必要もあるだろう。
そして、実メモリとしてPCに4GB以上積めるようになってしまったという話もある。
せっかく大きなメモリを乗せられるのだから32ビットであるがために利用できないのは残念だ。
もし実メモリが4GB以上あるなら64ビットに移行するのに異論はなかろう。
ただし、64ビットには16ビットから32ビットになったときほどの便利さは無いと思う。
16ビットでは64KBの制限がありセグメント切り替えなんて面倒なことをやっていた。
32ビットが出てからはセグメントを気にしなくてもよくなったし、
64KBを超えるデータが楽に扱えるようになったのは大きかったように思う。
現状では32ビット環境で4GBのメモリが足りないという実感を持っている人は少ないと思う。
大量のメモリを使うことで性能を発揮するようなソフトウェアが出回れば、
例えば推奨メモリ量が4GBだとか8GBであれば需要が増えるかもしれない。
64ビットへの対応はソフトウェアの開発者から見るとそれほど敷居は高くない。
よって、ハードウェアの状況を見極めて対応していく必要があると思われる。
一方、64ビットのデメリットについても言われている。
これには命令やアドレスが64ビット幅になるので実行ファイルが大きくなることがある。
確かにメモリを多く食うし、キャッシュのヒット率は理論上は下がりそうである。
ただし、これは実際の動作を検証しないとなんとも言えない。
メモリが増えると自ずとディスクへのアクセスは減るので速くなる可能性がある。
64ビットとしての全体の環境が最終的に効率を上げる可能性は十分にある。

一般ユーザーの目線に立って考えてみる。
64ビットでも32ビットのソフトウェアは動くので問題無い。
逆に、64ビットのソフトウェアは32ビット環境では動作しない。
64ビット環境では16ビットのソフトウェアは動作しない。
64ビットのソフトウェアは32ビットのDLLを使えない。
(64ビットのPCでも32ビットのソフトウェアであれば32ビットDLLは使える。)
逆に、32ビットのソフトウェアは64ビットのDLLを使えない。
ソフトウェア自体は動くがプラグインが使えないという場合がでてくるかもしれない。
64ビットであればメモリを大量に使うソフトウェアの動作が向上する。
そして、レジスタが増えるので、ほとんどの処理の速度が上がると思われる。
逆に、書く処理によっては遅くなることも無いことはないだろう。
将来的に大量にメモリを使う64ビット対応のソフトウェアを使う予定があれば64ビットは有利である。
ハードウェアについては64ビットに対応かどうかを確認することが大切。
ドライバに関しては64ビット環境で32ビットのドライバは使えない。
64ビット環境では64ビット対応のハードウェアと64ビット対応のドライバが必要である。
ともあれ、32ビットと64ビットのどちらを選択するかは「64ビット専用で32ビットはサポートしない」、
と言われる時代が来るまでは32ビットを選択しておけば安心だと思われる。
もし余裕と興味があれば64ビットに手をだすのもいいかもしれない。
実際使用してみると64ビットの操作感は32ビットとなんら変わるわけではない。
何か古いものや新しいものを追加するときに苦労するかもしれないだけだ。

1、メモリ

32ビットでは利用できるメモリは最大4GBという壁があった。
一方、64ビットでは16TBものメモリ空間を利用できる。
また、32ビットではシステム領域がメモリを使用するので、
最大4GBといっても実情はせいぜいユーザー領域として3GBしか利用できなかった。
しかし、64ビットでは32ビットのソフトウェアであっても、
ユーザー領域として最大4GBを使用できる。

2、レジスタ

すべての汎用レジスタの幅が最大32ビットから64ビットになる。
例えば、AXは32ビットでは最大幅32ビットでEAXと書いたが、
64ビットでは64ビット幅でRAXと書いて使用できる。
また、汎用レジスタが32ビットは8本だったが、64ビットでは16本になる。
32ビットでは、AX、BX、CX、DX、BP、SP、DI、SIの8本であるが、
64ビットでは、R8、R9、R10、R11、R12、R13、R14、R15が追加される。
書き方は、例えばR8と書くと64ビット幅となる。
R8の下位32ビットはR8Dと書き、下記16ビットはR8W、下記8ビットはR8Bと書く。
他に、64ビットではSSEレジスタの数が増える。
32ビットでは128ビット幅のXMM0〜XMM7で8本だった。
64ビットでは128ビット幅は変わらないが、XMM0〜XMM15の16本になる。

3、C言語

いちばん注意しないといけないことはポインタのサイズであろう。
32ビット環境ではポインタのサイズは4バイトであったが、
これが64ビット環境では8バイトになる。
構造体や配列のメモリのサイズや配置方法で問題が起こるかもしれない。
例えば、構造体の要素にバイト単位でアクセスする場合。
また、ポインタに関係するキャストなどで問題が起こる可能性があるかもしれない。
例えば、ポインタのアドレス値を整数型にキャストして代入する場合など。
次に問題になるのはデータ型に関してであろう。
int や long が何バイト幅になるかは環境によって異なる。
考えられるパターンとしては、

int 4バイト、long 4バイト
int 4バイト、long 8バイト
int 8バイト、long 8バイト

の3パターンだと思う。
実際にどうなるかはコンパイラのマニュアルを見るか sizeof で調べるなどすればいいと思う。
また、long long 型を使えば必ず8バイトになるようだが、
これに関してもコンパイラの仕様を確認いただきたい。
その他のデータ型に関してもサイズを確認しておくと良いだろう。
最後に、printf などについて %d が正常に動作しない可能性がある。
例えば、ある場合には %I64d になるようだが、
この動作に関してもコンパイラなどの仕様を調べる必要がある。

それ以外の問題としては、アセンブラを組み込む場合に、
関数での引数の引き渡し方やスタックフレームの作り方が違ってくるだろう。
その場合、Cをいったんアセンブラに展開して調査する必要があろう。

4、Windows

Windows では int も long も4バイトである。
8バイト幅を使いたい場合は long long 型を使う。
ポインタはもちろん8バイト。
データ型に関しては DWORD64 や INT64 が使用できる。
DWORD64 と書いておけば32ビットでコンパイルしても通る。
また、LONG_PTR というのもあり、これはポインタサイズの long という意味。
LONG_PTR のサイズは32ビットでは4バイト、64ビットでは8バイトである。
この LONG_PTR の注意は LONG_PTR はデータ型でありポインタでは無いところだ。
また、POINTER_32 や POINTER_64 というものもあり、
これは32ビットでも64ビットでもサイズが保障されたポインタである。
POINTER_32 は32ビットポインタであるし、POINTER_64 は64ビットポインタである。
また、ポインタに関連して、64ビットでは次のAPIが使えない。

GetClassLong
GetWindowLong
SetClassLong
SetWindowLong

それぞれ以下のAPIに置き換える。
以下のAPIは32ビット環境でも使えるようにできているようだ。

GetClassLongPtr
GetWindowLongPtr
SetClassLongPtr
SetWindowLongPtr

以上のことから、
32ビットしか考慮していないコードは64ビットのコンパイルで正常に動作しない可能性があるが、
(逆に、64ビットしか考慮していないコードは32ビットのコンパイルで正常に動作しない可能性があるが、)
新たな定義を使うことで32ビットでも64ビットでもコンパイルできるコードが書ける。
その他、printf を使う場合に64ビット値を表示するとき %I64d などを使う。

5、64ビットプログラムの開発

MicroSoft が提供する Visual Studio は64ビットのコンパイルに対応している。
(Visual Studio 自体は32ビットのソフトウェアである。)
無料の Visual C++ 2008 Express Edition を Windows7 64bit 上で試してみた。
通常は Express Edition では64ビットを使えないようだが、
設定を書き換えるバッチがありそれを使うことで64ビットを選択できるようになった。
バッチはレジストリの書き換えと設定ファイルの書き換え、DLL の置き換えをやっている。
あとは Windows SDK やら .NET Framework やらが必要とのこと。
これらの手順を紹介したページがいくつかあるので、
そちらを探して参照いただきたい。

inserted by FC2 system