エンディアンというのは、ワード(語)や、ビットの並び方の呼び名である。
ビットの場合、ビット・ナンバリング(ビットの番号づけ)ともいう。
ビットのエンディアン、ビット・ナンバリング(ビットの番号づけ)ともいう
ものの話をしよう。
80x86 は、ビットの名前が最下位ビットからついている。
つまり、最右ビット(最下位ビット(LSB)) が、bit 0 だ。
古いMacオタクの大好きな PowerPC は、ビットの名前が最上位(最左(MSB))から
ついている。最上位ビットが bit 0 だ。
LSB 0 ビット・ナンバリング x86, VAX, ARM, MIPS, 680x0, SPARC |
MSB 0 ビット・ナンバリング PowerPC,PA-RISC, S/390(メインフレーム) |
---|
さて、ここに古代Macオタクと、1980年代 UNIXワークステーション好きが、 超絶大好きな 68020,68030 というモトローラ(今では、フリースケール)のCPUがある。
68020は、68000の32bit強化版で、68000の命令はすべてそのまま実行できる。
68000は、32bitアーキテクチャの16bit実装ということで、偉そうにしていた。
(が、実は作った人は、そんなに頭が良くない)
68000は、ワードはモトローラ伝統のビッグ・エンディアン。
そして、ビットの名前は最下位(最右)ビットがbit0。
例えば 68000 から備わっている BTST(ビットテスト)命令は、
BTST.L #0,D0で、bit0すなわち 最右ビット(LSB)をテストする。
だがしかし、68020で新設の BFTST命令では、
BFTST D0{0:1}は、最上位(最左)ビット(MSB)をテストする。
BFTST D0{31:1}としなければならない。
なぜこんなことになったのか?
それは、ビットの拡張性の問題だ。
ビットは、ワード・エンディアンとは独立に拡張性がある。
しかし、それにしても、めちゃくちゃにやってはいけない。
LSB 0 ビット・ナンバリングは、 ワード・リトル・エンディアンである方向に拡張される |
MSB 0 ビット・ナンバリングは、 ワード・ビッグ・エンディアンである方向に拡張される |
---|
68000は、ワードがビッグ・エンディアンなのに、
LSB 0 ビット・ナンバリングにしたので、
本当に32bit 以上にしたとき、破綻した。
(拡張された部分の名前付けがうまくできなかった)
そして、仕方がないので、ビットの名前付けを逆(MSB 0 ビット・ナンバリング)に
修正した。
古い68000命令は、古いまま残して。
ビット・ナンバリングは、ビットマップ・ディスプレイを作るときにも影響した。
80x86で作った機械は、ハードウェア屋さんも何も考えずに素直に作っておけ ば、CPUが32bit化したときも、なにも考えずにそのままソフトウェアも全てつかえた。
68000は、メモリ空間がリニアで、ハードウェア屋さんも好きだった。
とくに、高解像度なグラフィック端末は、リニアなメモリ空間を必要としたので、
68000で、グラフィック端末を作った会社も多かった。
しかし、16bit機である68000で、32bit以上のメモリ配置を考えず、
68000のbit0(LSB) から表示した機械は、
それを32bit 化したとき、ソフトウェアは、32bit ワードを半分に切って、
入れ替えるとかいう、あほらしい手間が生じた。
(通常、ビットマップ・ディスプレイのハードウェアは、
bit0から表示するように設計する。
というか、ビット・シリアルなハードウェアは、LSBから出力するようにするのが、
ハードウェア設計の通常のやり方である)
なぜなら、ビットの拡張性が無く、16bit づつ切れていたからだ。
(だから、32bitアクセスすると16bit単位で上下が入れ替わる)
68000系を使った機械でも、頭のいい人が設計したハードウェアは、
68000のbit15(MSB: PowerPCのbit0)から表示していたので、
32bit化したときも問題なかった。
しかし、68000の機械語命令のビット名前の付け方から通常 想像される点の位置と、
実際に点の表示される位置が違うので、ソフトウェア屋は混乱した。
IBMは、ものがわかっているので、ワード・ビッグ・エンディアンである 伝統のメインフレーム S/390 (大昔の370シリーズ)も、 Power(PowerPCは、Powerのマイコン版)も、 MSB 0ビット・ナンバリングで作っている。
MIPSは、SGIを始めとする多くのUNIX系マシンで
ワード・ビッグ・エンディアンで使われている。
だが、LSB 0 ビット・ナンバリングであり、
それは本来、ワード・リトル用である。
MIPSをビッグ・エンディアンで使った会社のほとんどは、
680x0のマシンの後継として MIPS使用マシンを出したので仕方ない。
DECは、MIPSをワード・リトルで使っていた。DECは伝統的に
リトル・エンディアンの会社だから当然。
DECは、LSB 0ナンバリングの会社である。
SPARCは、基本がワード・ビッグ・エンディアンなのに、LSB 0ビット・ ナンバリングであった…
日立もワード・ビッグ・エンディアンの会社であるが、
SH-3, SH-4も、LSB 0 ビット・ナンバリングだった。
そもそも8bit時代に6800(六千八百)のセカンド・ソース作りとかやってたからだな…
6800, 6809は、モトローラの8bit。どちらも、ワードはビッグ・エンディアンだが、
LSB 0 ビット・ナンバリング。
6502は、ハードウェアは6800に似せてあるが、ワード(主にアドレス情報)は
リトル・エンディアン。
LSB 0ビット・ナンバリング。正解。
8080, Z80,80x86は、ワード・リトル・エンディアンで、
LSB 0ビット・ナンバリング。正解。
というか、8bit CPUで、MSB 0ビット・ナンバリングのCPUって、 メジャーなものには、なかった気がする…
古い16bit CPUである TI社の9900は、ワード・ビッグ・エンディアンで、
MSB 0 ビット・ナンバリング。正解。
通常、ハードウェアは、LSBから出力するので、その点でも、
LSB 0 ビット・ナンバリングが良い。
そして、LSB 0 ビット・ナンバリングを使用すると、拡張性を自然にしようとすると、
自ずとワード・リトル・エンディアンになる。
やはり、リトル・エンディアンを使う方が、正しいと思えるのだが。
MSB 0 ビット・ナンバリングで、グラフィックスのプログラムを書いてみれば、
ちょっと混乱するよ。慣れれば平気だけど。
LSB 0ビット・ナンバリングで、グラフィックスのドットがMSBから表示される
(68000系機械)の方が、もっとプログラマは混乱するかも知れない。
SGIとかのメジャーなグラフィック・マシンも、これなんだけど。
(だから、慣れている人は多い気がする)
ビット操作が、ワードで閉じてて、拡張を絶対にしないなら、
ビット・エンディアンは関係ないとも言える。
だが…
Ada95言語では、
record定義の中で、データのビット・エンディアンを指定できる。
この文書は、前半では本稿と同様の議論が、書かれている。
/*無くなった (^^; →
だが、
英語版Wikipediaの Bit numberingの項には、
Ada言語では、ビット・エンディアンが見えている、と出ている。*/
ちなみに、verilogなどのハードウェア記述言語では、ビットのオーダリングを個々に指定できるのはフツーである。