【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

Windows NT/Alpha用のクロスgcc

32bitのAlphaのコードがどのようなものか見たくなり、Windows NT/Alpha用のクロスgccをビルドしてみました。ビルドに成功したのはgcc-3.0.4です。binutilsはビルドできるバージョンが見つからなかったため、PEバイナリは出力できません。gcc -Sでアセンブリコードを出力することはできます。

ソースにパッチを当て、ソースの外にディレクトリを作ってビルドします。

$ tar xvzf gcc-core-3.0.4.tar.gz
$ patch -p0 < gcc-3.0.4-alpha-winnt.diff
$ mkdir alpha-winnt
$ cd alpha-winnt
$ ../gcc-3.0.4/configure --target=alpha-winnt --disable-nls
$ make
$ make install
  • ビルド用のディレクトリの名前は何でも良いです。
  • MSYSではconfigureを絶対パスで呼ぶとWindowsパスへの変換に失敗するため、相対パスで呼ぶ必要があります。
  • --disable-nlsを指定しているのは、日本語でメッセージが出るのを避けるためよりも、バイナリ配布したときにlibintlのバージョン違いで動かなかったことがあるためです。

サンプル

64bit用のalpha-elf-gccとの違いを比べてみます。alpha-elf-gccのビルドはパッチが必要です。

簡単なプログラムをアセンブリ出力して結果を比べてみます。

64bit (alpha-elf)

gccからアセンブリを出力します。プロローグやエピローグを簡略化するため最適化を掛けます。

$ alpha-elf-gcc -O -S -o alpha-elf.s alpha.c

binutilsが使えるので、逆アセンブルも試します。C言語との対応関係が分かります。

$ alpha-elf-gcc -nostdlib -O -g -o alpha-elf.x alpha.c
$ alpha-elf-objdump -S alpha-elf.x > alpha-elf.txt

レジスタが番号ではなく名前で示されるため読みやすいです。擬似命令が展開されるため、実際のバイナリが確認できます。

32bit (alpha-winnt)

gccからアセンブリを出力します。プロローグやエピローグを簡略化するため最適化を掛けます。

$ alpha-winnt-gcc -O -S -o alpha-winnt.s alpha.c

binutilsアセンブラ・逆アセンブラ・リンカなど)が使えないため、逆アセンブルはできません。

比較

両者を見比べると以下のことが分かります。

  • CPUに32bit/64bitのモードがあるわけではなく、コンパイラの出力でデータモデルを表現している。
  • 32bit(alpha-winnt)はILP32
lda $16,4 # sizeof(int)
lda $16,4 # sizeof(long)
lda $16,4 # sizeof(void *)
  • 64bit(alpha-elf)はI32LP64
lda a0,4 # sizeof(int)
lda a0,8 # sizeof(long)
lda a0,8 # sizeof(void *)
lda $1,global => ldq t0,-32760(gp)
  • 32bitではbinutilsが使えないため確認できない。GPレジスタを操作しないことから、絶対アドレスが2命令に分割された上で即値として埋め込まれると思われる。
  • よく似ているMIPS(mipsel-pe-gcc)で例示(←ビルド方法など
sw $4,global => lui at,0x40; sw a0,8192(at)
# [0x402000] = a0

おまけ

gcc-3.0.4にはalpha-interixのコンフィギュレーションもあります。出力するコードはalpha-winntとほぼ同じようです。こちらも対応するbinutilsが見つかりませんでした。

Alpha版のInterixは存在すら知らなかったので驚きました。WikipediaにはInterix 2.2までは対応していたような記述があります。

現物は見たことも聞いたこともないので詳細不明です。