SSブログ

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

ああ、ようやくサウンド関係のファイルを読み込んだぞ。不正ディスクを除外したので、これでやっとBGMを鳴らそうという事らしい。しかし、ゲーム本体への道のりはまだあまりに遠い。

あまりに遠そうだから、どれだけ遠いか、ゲームを起動して確認してみた。ああ、まだプレーヤーの名前を決定していない。私にとって不要なルーチンが山のように出てくるらしいぞ。BGMだって、それ自体は興味深い学習対象だが私の目的とは関係しない。

これは、もう、ちょっと辛すぎるかも。

DOSのファイル名を使ってディスクからデータをバッファに読み込むルーチンはすでに出てきているし、その時にデータセグメントのどういうアドレスを指定したら良いかもわかっている。ということは、データセグメント内にあるファイル名からサブルーチンに渡すアドレスがわかるので、プログラムを組んでEXEファイル内を検索して、そのコードを見つけ出せば、不要な山のようにあるルーチンを飛び越えて本当に解析するべき部分にたどり着けないだろうか。

この試みを始めた頃はMS-DOS時代のEXEファイルの構造がわからないでいたが、実はあれから情報収集したので少しだけわかった。

昔のEXEファイルは、まずヘッダがあり、その後にロードモジュールがあった。ヘッダのオフセット08Hからの2バイトに、ヘッダのサイズが入っている。これは同時にヘッダの直後から始まるロードモジュールの開始点でもある。ただしサイズは、16バイトパラグラフ単位で入っている。ヘッダ内のオフセット16Hからの2バイトに、ロードモジュール内のコードセグメントのオフセットが入っている。ただしこれも、16バイトパラグラフ単位で入っている。

これだけではまだ足りない。データセグメントという言葉がどこにも出てこない。ロードモジュール内のデータセグメントのオフセットはどこだ。データセグメントやコードセグメントの情報は何バイトロードされるのか。そのへんの事が、必ずわかるようになっているはずなのだが。

とにかく試してみよう。

私はt.exeをバイナリエディタ(ビューアーとして使う)に読み込んだ。ファイル先頭からオフセット08H以降の2バイトは、00C0H。これに10Hを掛けると、0C00H。バイナリエディタでその場所を見ると、前も後も00Hだらけだ。本当にここがロードモジュールの先頭アドレスなのか。

00Hばっかりだから、見るからにコードセグメントにロードされる情報ではない。データセグメントにロードされるのかもしれない。PC-98エミュ内でdias.exeを使い、データセグメントの内容を表示して比べよう。今までの解析で、データセグメントが1D7CHだということはわかっている。それ以降00Hがずっと続き、初めて00H以外が出てくるのが1D7C:1134だ。
TT08.png

次に、EXEファイル内を見ているバイナリエディタのほうで0C00H + 1134H = 1D34Hを見てみた。(ドキドキ。)
TT09.png

よっしゃぁッ!データセグメントにロードされる内容は、EXEファイル先頭からオフセット08H以降に格納されている2バイトの値に10Hを掛けた値をEXEファイル先頭からのオフセットとする場所から始まっている。(どこまで続くかは知らないが。)ロードモジュール先頭にはまずデータセグメント用の情報があるのだ。

今度はコードセグメント用の情報の場所を確認する。EXEファイル内を見ているバイナリエディタのほうでファイル先頭からオフセット16H以降の2バイトを見ると0EF4H。これに10Hを掛け、先ほど調べた0C00H(ロードモジュール先頭をEXEファイル先頭からのオフセットで表した値)に足すと、FB40H。
tt10.png

これがdias.exeにt.exeを読み込んでuとだけコマンド入力してEnter押した時(コードセグメント先頭からの逆アセンブル)と同じならば全部オッケーだ。
tt11.png

はうう!なんか違っ・・・!なんかまたドキドキしてきたッ!B8 7C 1Dでなきゃいけないのに、B8 00 00じゃないか。

それから私は、ちょっとパニックになり、使っているバイナリエディタの機能でB8 7C 1Dを検索した。検索のしかたがわからなくてヘルプを参照しようと思ったら昔のhlpファイルだから開けなくて、hlpファイルを開くソフトをマイクロソフトが提供しているようだからダウンロードしたらどれもこれもWindows10に対応していなくて、ネット上に有難いパッチを見つけて、それだけの苦労をして検索した結果、B8 7C 1DはEXEファイル内に存在しないことがわかった!なんだとぉぉぉぉ!だって逆アセンブル結果にあるじゃん。B8 7C 1Dって。そう考える間も私の頭の片隅で常に何か声がしていた。前から思っていた疑問。EXEファイルの中身がPCのメモリにロードされる前に、どのアドレスにロードされるかわかってない気がするんだけど。でも逆アセンブルしたコードにはいろんな場所のアドレスが書いてある。オフセットはいいとしてセグメント値はメモリにロードされる時点ではじめて決まるんじゃないかなあ。それともEXEファイルにあらかじめ書かれたセグメントにプログラムがきっちりロードされるのかなあ。だって、EXEファイル内のコードに大量に書かれたセグメントのデータを、プログラムをPCのメモリにロードする時点で瞬時にバババッと書き換えるなんていう大変なことを、しているわけがないから。・・・と、思っていたけど、しているわけなんですね!ああ、ひょっとして、それがあの、私が理解不能で読み飛ばしたリロケーションテーブルとかいうものの機能なんでしょうか。

ここまででわかったこと。上記の方法でコードセグメントにロードされる情報の先頭がEXEファイル内のどこに相当するかがわかる。ただしコードセグメントの情報だろうとデータセグメントの情報だろうと、その中にある(グラフィックVRAMのように固定した値を除いて)セグメントの値は、PCのメモリにロードされる時点ではじめて決定されるので、EXEファイル内のデータとメモリにロードされたデータが異なる。もしもdias.exeで逆アセンブルした結果を元にEXEファイル内のバイナリデータを検索しようとするならば、その検索キーにセグメント値が含まれていると失敗する。

コメント(0) 

コメント 0

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