BOMの話をする前に、まずは「バイトオーダー」というものについて理解する必要があります。
現在使われているコンピューターは、データの記憶装置(メモリやファイル)上への保持の論理的な最小単位が1バイト(=8ビット)です。なので、記憶装置上では、すべてバイトの列として扱う事になります。
すべてのバイトには、それぞれユニークな位置(アドレス)が結びついており、隣り合ったバイトではアドレスが1ずつ増えていきます。
バイト1 →アドレスnバイト2 →アドレスn+1:と言った具合です。処理するデータは、それぞれのバイトに格納されており、アドレスを指定してデータを読み取ったり書き込んだりします。
さて、話がこれだけなら単純なのですが、問題なのは,コンピュータが扱うデータの大きさは、1バイト(8ビット)で収まらない事が多いということです。
たとえば、255を越える整数は1バイトに収まらないですし、ASCIIではない、日本語などを含む文字1つを表すにも、1バイトでは足りません。
どうするかというと、もちろん複数のバイトを使うのです。いくつかのバイトを合わせて、1つのデータを表現します。
2バイト(16ビット)あれば、0から65535までの符号無し整数を表現できますし、あるいは-32768から+32767の符号付き整数を表す事ができます。1バイトで256通りの数をあらわせるのだから、2バイトなら256x256とおりの数を表すことができるというわけです。これは、0から9までの数字を1つ使えば0から9までの数(つまり10とおり)が、2つつかえば、00から99までの数(つまり10x10=100とおり)が表せるという事と同じです。
このように、2つ(もしくは複数)のバイトを使って数値をあらわすとき、上位の桁を表すバイトを「上位バイト」と、下位の桁を表すバイトを「下位バイト」と呼びます。
さて、ここまでは良いでしょう。
問題は、2バイトのサイズが格納に必要なデータを、2バイトで表してメモリ上に保存しようとするとき、バイトの列であるメモリにその2バイトをどうやって並べるかです。
(案1)上位バイト、下位バイトの順序に並べる(案2)下位バイト、上位バイトの順序に並べるこの2の方針のうち、どっちが正しいでしょうか。明らかでしょうか? いや、この問題は、それほど自明ではないのです。
わたしたちは普通、数字を紙に書くとき、たとえば78という数字を書くとき、7を書いてから、その次に8を並べて書きます。つまり、案1に従っています。
なので、コンピューターも(案1)に従えばいい、というのは確かに一つの見識です。
でも(案2)には捨てがたいものがあるのです。たとえば、足し算をするときには、下の桁から足していって、繰り上がりとか計算しますよね。(案2)の方が計算順序通りに並んでいるので都合が良い。また、「アドレス」でこの2バイトの値をポイントしようとすると、先頭バイトを示すのですが、(案2)であると、アドレスから下位1バイトが何か、をすぐに知る事ができます。コンピューターでは、数値がある範囲を超えたら切り捨てる計算をする事が良くあるのですが、たとえば、256を越えたら0に戻るような計算をするときがあるのですが、複数バイトからなるデータを表すときに、データの先頭アドレスが下位バイトを指していると、その先を「何バイトの整数と見て取り出すか」で切り捨て処理をおこなっていることになり、(多少)都合が良いのです。
ということで、コンピューターの世界では、結局この2つの流儀がまかり通る事になっています。これらをバイトオーダー(バイト順序)の問題と呼びます。
ちなみに(案1)をビッグエンディアン、(案2)をリトルエンディアンと呼びます。これはガリバー旅行記に出てきた、「ゆでたまごを太い方から食べる流儀の人々」と、「細い方から食べる人々」がそれぞれそう呼ばれていた事に由来するそうです。「どっちでもいいのに、とことんこだわって妥協しない事」を揶揄した、ユーモアの或る呼び方ですね。
なお、歴史的には、この2つの流儀は、CPUのメーカによる流派でもありました。つまり、インテル(8080,8086,..)はリトルエンディアン派、モトローラ(MC6800系)はビッグエンディアン派です。細かいことを言うとさらにいろいろあるのですが割愛します。
ここまでをまとめると、複数のバイトで表現しなければならない整数データをバイト列として保存する際には、上位からならべるか、下位から並べるか、といった方針を決めなければならないということです。また、その方針は、1台のコンピュータ上で処理が完結しているならあまり問題にならないのですが、複数のコンピュータ間でデータ交換を行う場合です。データを作成した側と、データを読み取る側で、その方針が一致していなければ,正しいデータを読み取る事は不可能です。
このような、コンピューター間でデータをやり取りする際に、バイトオーダーの問題をどう解決するかですが、
(案A)決める。例えば、「案2」を「ネットワークバイトオーダー」と名付け、通信ではこれを使うのだと決める。TCP/IPの通信の世界ではこうやっています。あるいはDOSのファイルではこうだとかプロトコルやフォーマットとして決めます。(案B)データ中に、どっちの順序を使っているかを示すマーカーを含め、それをデータ自体と合わせて送受信し、データの読み取り処理はそれに合わせて変化させる。ここまで説明すると、結論は言わずとも明らかだと思いますが、いちおう本題に戻ります。
Unicodeの文字集合の文字データは、まさしく8ビットで収まらないデータであるわけですが、これをどっちの順序(ビッグエンディアン、リトルエンディアン)で保存しているかをデータの始まりに書いておこう、という方式があります。それがどっちかを表すマーカーデータが、バイトオーダーマークであります。