エンディアン
エンディアン (英: endianness) とは、多バイトのデータ(即ち基本情報記憶単位を超えるデータ)をメモリ上に配置する方式の種類のこと。エンディアンネス 、バイト順、バイトオーダ (英: byte order) ともいう。
日本では「エンディアン」という呼称が広く使われているが、英語の「endian」という単語自体には「配置方式」「並び順」といった意味はない。(#語源)
目次 |
概要 [編集]
例えば 1234ABCD(16進数)という4バイトのデータを、データの上位バイトからメモリに「12 34 AB CD」と並べる方式をビッグエンディアン[1]、データの下位バイトから「CD AB 34 12」と並べる方式をリトルエンディアン[2]という。その他に「34 12 CD AB」あるいは「AB CD 12 34」のように並べる方式もあり、ミドルエンディアン[3]、あるいはDECのPDP-11で使われていたことからPDPエンディアンなどと呼ばれるが、現在ではほとんど見られない。
ビッグエンディアンは人間にとって直観的にわかりやすいという利点があり、一方リトルエンディアンはコンピュータにとって処理しやすい(多倍長加算の起点は最下位バイトであることなど)という利点がある。
IBMのメインフレーム(及び互換機)、モトローラのMC68000(及び後継)、サン・マイクロシステムズのSPARC等はビッグエンディアンを採用し、DECのVAX、インテルのx86等はリトルエンディアンを採用している。ARMアーキテクチャ、トランスメタのCrusoe、ヒューレット・パッカードのPA-RISC、PowerPCなど、エンディアンを切り替えられるバイエンディアン (bi-endian) のプロセッサも存在する。ただし稼動CPUを問わずJava仮想マシンについてはビッグエンディアンである。
互換性・移植性 [編集]
エンディアンの相違は、単一あるいは同種のシステムに閉じた運用をする限りでは通常は問題にならないが、以下のような場合に問題になることがある。
- ネットワークを通してバイト単位でデータをやりとりする場合
- 異なるシステム間でバイナリファイル等を交換する場合
- 異なるシステムにプログラムを移植する場合
- 構成するプロセッサが異なるマルチプロセッサ環境で共有メモリを使用する場合
TCP/IPネットワークでは、エンディアンの異なるコンピュータ間での通信を可能とするため、パケットなどに含まれる多バイトデータはビッグエンディアンに統一することと決められている。これをネットワークバイトオーダという。これに対し、それぞれのコンピュータ上でのエンディアンのことをホストバイトオーダという。
画像や音声などのバイナリファイルにおいても、互換性を確保するため、エンディアンが規定されている例が多い。
Unicodeにおいても、構成要素が多バイトとなるエンコーディング(主にUTF-16)では、エンディアンが問題となる。そのため、バイト順マーク[4](英: Byte Order Mark、略語:BOM)と呼ばれる特殊なコード (U+FEFF) が予約されており、データの先頭にこれを付与することで、データを受け取る側がエンディアンを判別できるようになっている。BOMがない場合には、ビッグエンディアンだと決められている(→ UTF-16)。
ただし、復号側が以上のルールでエンディアンを判別する狭義のUTF-16とは別に、エンディアンを事前に一方に決定しているUTF-16BEとUTF-16LEが存在する。Windows上の文書における「Unicodeテキスト」は、BOMがない場合、UTF-16LE(リトルエンディアン)である。
例 [編集]
より詳しく説明するため、この章では最も一般的な32ビット機のエンディアンの例を示す。
すべての例は 0A0B0C0D という値をメモリに格納した場合を示している。
ビッグエンディアン [編集]
- 8bitで1ずつアドレスが増加する場合
| アドレス増加 → | |||||
| 0A | 0B | 0C | 0D | ||
例では最上位バイト (MSB) は0Aとなり、メモリ上では一番低いアドレスに保存され、次のバイト 0Bは続いて格納される。これは16進で左から右に読むのに似ている。
- 16bitで1ずつアドレス増加する場合
| アドレス増加 → | |||||
| 0A0B | 0C0D | ||||
最上位に0A0Bが保存され、続いて0C0Dが保存される。
リトルエンディアン [編集]
- 8bitで1ずつアドレスが増加する場合
| アドレス増加 → | |||||
| 0D | 0C | 0B | 0A | ||
最下位バイト(LSB)は0Dで、そのアドレスは一番低い。他のバイトはアドレス増加に追従する。
- 16bitで1ずつアドレス増加する場合
| アドレス増加 → | |||||
| 0C0D | 0A0B | ||||
16ビットで格納されている最下位の値は0C0Dで続いて0A0Bが入る。
ミドルエンディアン [編集]
さらに他のアーキテクチャでは、ミドルエンディアン又はミックスドエンディアンと一般的には呼ばれるさらに込み入ったバイトオーダもある。
例えばPDP-11であれば、最上位バイトから「0B」「0A」「0D」「0C」の順に格納される。つまり、最上位ハーフ(16ビット)と次のハーフ(16ビット)がビッグエンディアンで格納され、各ハーフ(16ビット)内の各バイトはリトルエンディアンとして格納される。これはPDP-エンディアンと知られている。
- PDP-11に32ビットワードを格納する場合
| アドレス増加 → | |||||
| 0B | 0A | 0D | 0C | ||
ARMアーキテクチャは32ビットワードを32ビットワードから2バイトに格納した場合、このエンディアンを生成することができる。
エンディアンの確認 [編集]
od コマンド [編集]
UNIX や Linux においては多くの環境にインストールされているodコマンドがエンディアン依存の実行結果を表示するため、odコマンドで実行環境のエンディアンを確認することができる。
$ echo -n "12345" | od -t x
32bit機ビッグエンディアンでの出力結果
0000000 31323334 35000000 0000005
32bit機リトルエンディアンでの出力結果
0000000 34333231 00000035 0000005
C言語 [編集]
C言語では共用体を使ってエンディアンを確かめることが出来る。ただし、標準規格では処理系定義とされている動作に依存している。[5]
#include <stdio.h> int main (int argc, char **argv) { union { int b4 ; /* 4byte */ unsigned short b2 [2] ; /* 2byte×2 */ unsigned char b1 [4] ; /* 1byte×4 */ } bytes ; bytes.b4 = 0x12345678 ; printf ("bytes.b4: %08X\n", bytes.b4) ; printf ("bytes.b2: %04X, %04X\n", bytes.b2[0], bytes.b2[1]) ; printf ("bytes.b1: %02X, %02X, %02X, %02X\n", bytes.b1[0], bytes.b1[1], bytes.b1[2], bytes.b1[3]) ; return 0 ; }
32ビット機ビッグエンディアンでの出力結果
bytes.b4: 12345678 bytes.b2: 1234, 5678 bytes.b1: 12, 34, 56, 78
32ビット機リトルエンディアンでの出力結果
bytes.b4: 12345678 bytes.b2: 5678, 1234 bytes.b1: 78, 56, 34, 12
となる。
語源 [編集]
ビッグエンディアンとリトルエンディアンという単語は、ジョナサン・スウィフトの風刺小説『ガリヴァー旅行記』の中のエピソードに由来する。ガリバー旅行記の第1部「小人国」では、卵を丸い方(大きい方)の端から割る人々 (英: Big Endians) と尖った方(小さい方)の端から割る人々 (Little Endians) との対立が描かれている。
この語を計算機に転用したのはDanny Cohen(en:Danny Cohen (engineer))で、1980年のpaper "On Holy Wars and a Plea for Peace"[6][7]で広く知られるようになった。日本では坂村健が広めたような覚えがある、としている文献がある[8]。
脚注 [編集]
- ^ 英: big endian
- ^ little endian
- ^ 英: middle endian
- ^ Unicode Terminology English - Japanese, B, Unicode, Inc.
- ^ 標準規格では、共用体を使って、同じ領域を異なる型としてアクセスした場合は処理系定義である。ポインタを使ってアクセスするのは、strict aliasing ruleにより未定義であるので良くない。ここで示しているコードは Visual Studio 2008 C++ Express Edition、GCC3.4.5-20060117-3 で動作確認済み。共用体の要素
b2とb4が符号なし(unsigned)になっているのは、printf関数の仮引数に値を受け渡すコードを処理系が生成する際に、最上位ビットの値に関係なく正の数として扱うコードにするよう処理系に指示するためのものである。 - ^ IEN 137 (1 April 1980) http://www.ietf.org/rfc/ien/ien137.txt これ以前の用語が「byte order」であったことなどもわかる
- ^ D. Cohen. 1981. On Holy Wars and a Plea for Peace. Computer 14, 10 (October 1981), 48-54. DOI=10.1109/C-M.1981.220208 http://dx.doi.org/10.1109/C-M.1981.220208
- ^ 中森章『マイクロプロセッサ・アーキテクチャ入門』p. 18 コラム