SSブログ

孤独へ向って突っ走れ (47) [  PC-98x1(補完計画)]

最近の記事で、本命と思われる巨大なサブルーチンに突き当たったと書いた。今日はそれの全体像がわかっただけでなく、私の固い頭を柔らかくしてくれる発想が出てきた。

解析を続けてさらにわかったことがある。現在解析中のものはサブルーチンではなかった。サブルーチンならばcallで呼び出され、retで呼び出し元に処理が戻るはずだ。ところがこのルーチンの先頭アドレスへ処理が移る時は、jmpで飛んでくる。サブルーチンとは呼べないからメインルーチンの一部というべきなのだろうが、アドレス的にはまるでサブルーチンのように、プログラム開始点から続くメインルーチンのアドレスとは離れている。これは特殊な事例だと思う。普通はこういうものをサブルーチンで実現する。一般には、サブルーチンへ処理を移したらいずれ呼び出し元に戻らなければならない。しかしこれはPC-98ゲームだ。当時のゲームは終了後にDOSに戻らないものが多かった。だからゲーム終了時には適当な場所で無限ループを作ってそこまでとできる。呼び出し元に戻る必要がない。戻る必要がないのだからcallする(IPの値をスタックに退避する)必要もない。retもない。私は今まで、コード内のretを目安にサブルーチンの始まりと終わりを探してきた。サブルーチン内に複数のretがある場合もあるが、それでもとにかくサブルーチンの終わりにはretがあり、始まりのひとつ前の命令は別のサブルーチンのretかiretだろう。しかし今回のルーチンはサブルーチンではないので終わりにretがなく、私はその後のアドレスに続く別のサブルーチンをこのルーチンの一部と思いretを探し続けた。さらに運が悪いことに、ルーチンの始まりのほうも同様の事情だった。つまり、アドレス的にひとつ前のルーチンが、これもまた同様にサブルーチンではなく終わりにretがなかったから、私はアドレスを遡ってルーチンの始まりを調べるさいも別のルーチンをこのルーチンの一部と思いさらに遡って調べた。その結果、このルーチンはたしかに巨大だが、それ以上に巨大に見えてしまった。私が誤りに気づくことができたのは、このルーチンのひとつ前のルーチンが「ゲームオーバー表示と無限ループ」だったからだ。無限ループまで来たらそのルーチンの処理は終わっているはず。でもretがない。よくよく考えてみたら処理を呼び出し元に戻さないのだからretはいらない。それで、これがサブルーチンではないと気づいた。
コメント(0) 

コメント 0

コメントの受付は締め切りました