LinuxバイナリはWindows上でも動作可能か?

 別に開発の話題でもないのですが、専門的な話題なので「開発」のカテゴリに区分けしておきます。
 
 朝方(午前4時頃)にPascalとMSNでちょっとした話になる。なにやら授業の課題で「Linux上で動作する実行ファイルは、Windows上で動作させられるか?出来ないのであれば、その理由を述べよ」という問題が出たらしい。
 
 おそらく、その課題の答えは「動作させることが出来ない、理由は実行ファイルの形式がWindowsとLinuxで異なるためローダーが対応していないから」という答えを求めていると思うのだが、それでは他の人の答えと同じで面白くないだろう。そういうわけで、「どうすればLinuxバイナリをWindows上で動作させることが出来るか?」というところまで突き詰めてみることにした。
 
 元を正せばOSが違うとはいえ、同一アーキテクチャー上で動作するプログラムである。演算命令やレジスタの扱いは全く一緒のはずで、その部分をWindows上に移植すれば全く同じ結果が得られるはずである。
 
 早速以下のようなコードを書いて、gccVC++でコンパイルしてみた。


int main(void){
int a=10;
return a;
}

 
 gccでコンパイルしたほうが7000バイト程度に対して、VC++でコンパイルした実行ファイルは26000バイト程度になった。stdio.hを組み込むとややこしくなるのが明白だったので、int型のaに10を代入して、それをリターンするだけのプログラムにしてみた。VC++でコンパイルされた実行ファイルを見てみると、プログラムは4096バイト目から開始されていて、0〜4095バイト目までは、MS-DOS上で動かしたときの処理が書かれているようだ。デフォルトでは「このプログラムはMS-DOS上では動作しません」的な内容が記述されている。
 
 ちなみにWindowsではMicrosoft PE・Microsoft COFFという形式で実行ファイルを構成している。これらの仕様は以下のURLに書いてある。ひげぽん氏のブックマークから発見した。
 
 http://www.interq.or.jp/chubu/r6/reasm/PE_FORMAT/intro.html
 
 OllyDbgを利用して、バイナリをトレースし、機械語を読んでいくとEAXレジスタに10を格納する部分を発見。しかし、そのバイナリパターンをgccでコンパイルした実行ファイル側で探してみたのだが見つからなかった。どうやら別の手段を用いているようだ。
 
 LinuxはELFというバイナリ形式を採用している。ELFの仕様はここでは紹介しないが、以下のページを読むとELFの仕組みが分かるだろう。
 
 http://ukai.jp/debuan/2002w/elf.txt
 
 結局のところ同じアセンブリコードで記述しているわけではなかったが、演算部分を差し替えれば動きそうなことはなんとなく分かった。ただし、これは全てのオブジェクトが静的リンクされていて、関数の呼び出しなどが全て自分の実行ファイルの中で完結している場合のみの話で、外部の動的ライブラリを利用している場合は、話が少し異なってくる。
 
 そんな感じで話がまとまった頃には、既にスズメが鳴く時間帯になっていましたとさ。