ロビ1のCALL命令
2024年5月6日


 今回ロビの稼働時間計測プログラムをロビ1で動かそうとしましたが途中でロビが停止してしまいました。
 原因を調べていくうちにいろいろ事が分かったので今回記事にしておきます。

 稼働時間計測プログラムはロビ音頭を連続して踊らせて何回踊れるか計測しています。
 稼働時間計測プログラムからロビ音頭のプログラム呼び出しています。
 ロビ1のプログラムでは以前ロビ音頭をロビ1に移植したものを使いました。
 停止した原因はCALL命令の階層の制限を越えてしまったからでした。
 ロビ1のCALL命令は3階層までしか呼べません。
 稼働時間計測プログラムはmain5_InitFlag確認補完無し_シーン1固定0415_test2.RM4→聞き音声にモーション4.RM4→ランダム\114.RM4(稼働時間計測プログラム)→ロビ音頭(ロビ1).RM4と呼ばれます
 ロビ音頭でcall命令を実行した所で階層の制限にひっかかりロビが停止していました。
 ロビ1のロビ音頭は1本のプログラムで完結しているはずでサブルーチンプログラムは提供しておらずcall命令は使っていないと認識していました。
 ロビ1のロビ音頭プログラムはロビ2のプログラム(STARTUP.BIN)のロビ音頭のサブルーチン部分をロビプログラムアナライザで自動的にロビ1のプログラム形式(RM4)に変換して作成しています。
 この時ロビプログラムアナライザの設定ミスで本来「CALL抑制」で変換すべきところをそのまま変換したためロビ2のcall命令をそのまま書き出してしまいました。
 このプログラムはロビ1でちゃんと動いていたのでこのミスに気が付きませんでした。
 今回このCALL命令が制限にひっかかってしまいました。

call adr命令

 ロビ1に移植した音頭プログラムですがcall adr命令を使っているのになぜエラーにならずにプログラムが実行できるのか考察してみました。
 ロビ1のjump命令は一般的にはjump adr命令を使っています。
 飛び先をプログラムファイルのバイトアドレスで指定します。
 それとは別にjump filenameという命令で別のプログラムファイルに直接ジャンプする命令があります。
 実際ロビ1のプログラムでは起動プログラム(STARTUP.XML)の最後でmain5_InitFlag確認補完無し_シーン1固定0415_test2.RM4(メインプログラム)にジャンプしています。

 call命令もjump命令のjump filenameとjump adr同様にcall filenameとcall adrの両方有効だと考えられます。
 call adrの場合はjump adrと同様プログラムファイルのバイトアドレスを指定するのだと考えられます。
 なお実際のロビ1のプログラム(特別版も含む)ではcall adrは全く使われていません。

call adr/jump adrのバイト位置

 もうひとつの疑問はロビ1に移植した音頭プログラムのcall adr命令のバイトアドレスがロビ2のままのになぜエラーにならずにプログラムが実行できるのか考察してみました。
 通常のロビ1のプログラムではjump adrのアドレスはジャンプ先のヘッダーのバイト位置を指定します。
 少しでもこの位置がずれてしまうと飛び先の命令を実行する時にエラーになってしまいます。
 ロビ2のjump adrやcall adrはSTARTUP.BINのバイト位置なのでロビ1に比べてかなり大きいアドレスとなっています。
 ロビ1のプログラムファイルの大きさをはるかに越えてしまっています。

 そこで考えられるプログラムファイルの大きさを越えた場合はプログラムファイルの最後とみなすのではないかという事です。
 ロビ1のプログラムの仕様としてファイルの最後は何も記述されていない場合でも必ずreturn命令が実行されます。
 従ってロビ2のままアドレスでもcall adrは実行され何もしないでreturnするためエラーにならずにプログラムがちゃんと実行されるという事です。
 なおこの仕様はcall adrだけでなくjump adrでも当てはまりロビ1のプログラムでjump命令で最後にジャンプしてreturnしたい場合は必ずしもプログラムファイルの正確なアドレスではなく適当に大きな値にすればいいという事になります。

実際の検証

 以上の考察が正しい事をロビ1のプログラムを実際にロビ1で動かして検証してみました。

   

 今回作成したプログラムです
 ダウンロードして動かす場合は拡張子をRM4に変更してください。

 最初にいくよ音声コール(call adr)でいくよ音声をコールしてロビに「いくよ」と言わせています。
 次にファイル最後コール(call adr)でロビ2のままアドレスを指定してエラーとならずにプログラムが続行する事を確認しています。
 次にOK音声コール(call adr)でOK音声をコールしてロビに「OK」と言わせています。
 次にファイル最後ジャンプ(jump adr)でロビ2のままアドレスを指定してエラーとならずにプログラムが終了する事を確認しています。
 この命令が正しく実行されない場合は次の了解音声が実行されロビが「了解」と言いますが言わない事を確認しています。

目次に戻る