spimでMIPS32と戯れる


昨日から、clojureのソース追っかけで、マウスを押す指が痛くなってしまったので
しばし、Suspend する。
休みに入った時、ある人から常識でしょと言われて、「はじめて読む486」なんて
本を読んでいたんだが、やっと読み終わった。
私の結論は、80X86 って、増築に増築を重ねて、複雑怪奇になった温泉宿 だね。
迷子になるくらいなら、何も無い所にすぱっと立てたものの方がいいね、である。

と言う事で、rubyの会の高橋会長ご推薦の「計算機プログラミングの基礎概念」に
目を付けた。
とは言え、いきなりこの本に行き着いた訳ではなく、次回RHGの課題図書候補として
上がった、Real World Haskell とか、Let's over LAMBDA とかを見比べながら、この
本に行き着いたのだ。だって、すっきりと設計された MIPS32を題材に選んでいる
んだもん。言うなれば、80X86に対する反動でしょうか。

でも、MIPSなんて実機の手配が大変じゃろと思っていたら、上記リンクからDL出来る
資料の中で、spimと言うシュミレータがあると言う事が判明し、俄然やる気が出て
きて、発注しちゃいました。
高い本で地味だけど、GUIで何か作りましょうと言う、何ともつまらない(私に取ってですが)
ものよりは、よっぽどかそそられます。
そう、私のGUI熱は、昔のMac使いの時にすっかり冷めてしまったのです。
あの頃のMac Programmingを称して、「使って天国、作って地獄」ってのがありましたから。
これでも、一時 Inside Mac を全巻揃えて、チャレンジしたものなんですが。。。

spimの詳細を見ると分かりますが、Linux,*BSD,Mac,Windows等で動く事が確認されていますし
ソースも公開されているので、Solaris等にも簡単にインストール出来るでしょう。
私は安直に、FreeBSDのportsを使って入れたのと、Windows版のバイナリーも
入れておきました。
BSD版の方は、7.4版なのに、Windows版は、7.2.1とは、これいかに? 開発者の
方は、現在MSに居るそうなので、最新版に追従して欲しい所です。
(何?、ソースがあるんだから、最新版をWindowsでコンパイルしろ、ですって?
Windows用のまともな開発環境が手元に無いんで、それはご勘弁を。)

MIPSと言えば、ヘネパタ本でしょうが、それは割愛して、命令表だけは取り寄せて
おいた。

まずは、試運転ですね。
やっぱり、初めは "Hello world.\n" と言うのがお約束。
アセンブラのソースを、spimにロードして、run するだけ。あっけないなあ。

昔は、
1. 紙テープ(いつの時代だよ)から、editor を読み込ませる。
2. ソースを作成して、結果を紙テープにパンチする。
3. アセンブラーを紙テープから読み込ませる。
4. パンチしておいたソースをアセンブラに読み込ませる。
5. エラーがあったら、goto 1.
6. もう一回、ソースをアセンブラに読み込ませる。
7. エラーが有ったら、goto 1.
8. アセンブラーから、結果を紙テープに出力する。
9. 出力されたテープを、コンピュータに読み込ませる。
10. 実行してみる。
11. 暴走とか、期待する結果が得られなかったら、goto 1.

以上は、簡単なアセンブラの場合で、ソースが何本にもなる場合、
8と9の間に、リンカーを読み込ませる。8のテープを(何本も)読み込ませる。
リンカーが文句を言ったら、goto 1. 文句を言われなかったら、結果を紙テープに
出力して、9.へ、となる。

そのうち、このループを回すのが面倒になると、、、
コンピュータの上で、人間がbinaryパッチを当てるようになる。
bainaryパッチって簡単に言うと、エラールーチンに落ち込まないように、そこを
避けて、適当な所に Jump させ、そこで、正しいコードを(勿論、ハンドアセンブル
しておいて)実行して、元に戻る、って仕組み。

私は、こんな事を本業でやっていた訳では無いんだけれど、本業にしてる人と
仲良くしてたので、いつの間にか、身に付けちゃった。

さて、エラー大好き人間としては、エラーのあるアセンブラーソースを、食わせたら
どんな文句を言ってくるか、そういう所に喜びを感じてしまう、変態野郎が
お相手しますよ。
MIPS32って、80X86と違って、学校では結構人気みたいだけど、エラーへの対処って
ちゃんと教えているのかな?

さあ、楽しみの始まりだ! 
6章の例、hello.as を、改名して(エラーを仕込んで)eh.as として実験。

最初は、よくありそうな、文字列の閉じ " の忘れ。

[sakae@fb ~/mips32/programs-euc/chapter-06]$ spim
SPIM Version 7.4 of January 1, 2009
Copyright 1990-2004 by James R. Larus (larus@cs.wisc.edu).
All Rights Reserved.
See the file README for a full copyright notice.
Loaded: /usr/local/share/spim/exceptions.s
(spim) load "eh.as"
spim: (parser) Unknown character on line 7 of file eh.as
          # main: 実行を開始する部分
        li      $v0, 4  # 4 = 文字列表示のシステムコール番号
        la      $a0,msg # $a0 レジスタに、文字列の番地を入れる
        syscall         # システムコール呼び出し
        jr      $ra     # main の呼び出し元に戻り、プログラム終了

# end
Hello world.\n
                                                                                                                                                                                                                                    ^
spim: (parser) syntax error on line 8 of file eh.as
(spim) quit

7,8行目って言ってるから、まあ、いいでしょう。
次は、コードが始まるよのマーク .text をコメントアウトした場合

(spim) load "eh.as"
Target of jump differs in high-order 4 bits from instruction pc 0x400014

これは、難題だ。何とも私には推測できませんでした!
次は、main: を mai:と間違えてみる。

(spim) load "eh.as"
(spim) run
The following symbols are undefined:
main

Instruction references undefined symbol at 0x00400014
[0x00400014]    0x0c000000  jal 0x00000000 [main]           ; 180: jal main

ここで一句、 
「実行して気づく、わが身の、アホさかな」
どういうコードを吐いていたか、はななだ興味がある所ではありますが、
先に進みます。

インストラクションの間違い。これはスパッと指摘して欲しい所

(spim) load "eh.as"
spim: (parser) syntax error on line 14 of file eh.as
                laaa    $a0,msg # $a0 レジスタに、文字列の番地を入れる
                ^
ちゃんと指摘しましたねぇ。
もう一つ、ボーナス問題。 $って、焦っていると、抜かしそう。

spim: (parser) syntax error on line 14 of file eh.as
          la    a0,msg  # $a0 レジスタに、文字列の番地を入れる
             ^

と、まあ、こうやっていろいろやっていると、違った種類のエラーを幾つ出せる
かと言う、ゲームに発展します。
くれぐれも、ぬけがけして、

strings spim
とか、
面倒だ、ソースを読んじゃえは、ご法度ですぞ。