« RZ1Basic v0.2.3 公開 | トップページ | RZ1Basic v0.2.3日本語Win版 »

ROBOBASIC講座(PEEK、POKE その2)

前回の「ROBOBASIC講座(PEEK、POKE その1)」つづきです。

【答えと解説】

:サンプル2 答え「0x0D04」

《サンプル2》
TEMPO 230
MUSIC "C"
GOSUB test
MUSIC "E"
END

test:
MUSIC "D"
END

このソースの場合、3行目のGOSUBルーチンでtestへジャンプしたまま、プログラムを終了させたものです。これのプログラムでは、サブルーチン内でスタックポインタがひとつ(2バイト)増えていることを確認することができます。スタックポインタは、「ROBOBASIC講座(PEEK、POKE その1)」のBの図の状態の「0x0D04」になっていることが分りましたでしょうか。

 

:サンプル3 答え「0x0D00」

《サンプル3》
TEMPO 230
MUSIC "C"
GOTO test
MUSIC "E"
END

test:
MUSIC "D"
RETURN
END

このソースの場合、3行目のGOTOでtestへジャンプさせています。ジャンプ先のtestにはRETURNがあります。このプログラムは、GOTOでジャンプした場合に、RETURNが現れた時、スタックポインタがどうなるかを見たものになりますね。GOTOで呼ばれたのにも関わらず、スタックポインタはRETURNが呼ばれたことによって、スタックポインタはひとつ(2バイト)減って「0x0D00」になります。いろいろ変なコードを書いて試してみましたが、兎に角、スタックポインタが0x0D02より小さくなると、変なことが起こるようです。

では、スタックポインタが大きい方へはいくつまでいけるのでしょうか
以下のようなコードを書いてみました。

《サンプル4》

DIM RR AS BYTE
DIM a AS BYTE
DIM sp AS INTEGER

TEMPO 230

MAIN:
sp=PEEK(&h04D5)
IF sp<&h0D02 OR sp>&h0E00 THEN
    MUSIC "G"
    END
ENDIF
MUSIC "C"
GOSUB REMGET
GOTO MAIN
END

main_exit:
MUSIC "F"
GOTO MAIN
END

REMGET:
MUSIC "D"
if RR=0 then GOTO MAIN1
GOTO main_exit
END

MAIN1:
MUSIC
"E"
a
=REMOCON(1)
ON
a GOTO MAIN
GOTO main_exit
END

これは、「基本モーション1」を簡略化したものです(参考)。「基本モーション1」で、RR=0でA=0の場合、つまり、な〜んもしてない時、MAIN->REMGET->MAIN1->MAINとグルグル回っている仕組みになっています。でもMAINの中がGOSUBで呼び出しているのに、RETURNなしでMAINに返ってきてしまうため、スタックポインタが、どんどん増えて行くはずですよね。

MAINに戻った時、スタックポインタが0x0D02であるのが本来だと思いますので、PEEKコマンドを使って、スタックポインタの値を調べて、0x0D02以外だったら、プログラムを止めるというプログラムを書込んでおけば、どこかでプログラムミスをしてた時、安心ですね。

sp=PEEK(&h04D5)
IF sp<>&h0D02 THEN
    MUSIC "G"
    END
ENDIF

で、サンプル4では、0x0D02以下の場合、変なことが起こることはサンプル3でわかったので、大きい方が、どこまで大きくなったら変なことが起こるのかを調べることが目的なので以下のようにしてみました。

IF sp<&h0D02 OR sp>&h0E00 THEN

だんだん数値を大きくして行きましたが、0x0E00でも、いちおう変にはなりませんでした。
ROBOBASIC講座(GOSUB...RETURN)に、GOSUBで呼べるのは5回までマニュアルに5回と書いてある)と書きましたが、そうでも無いみたいですねここではコードは書きませんが、5回を超えるとRETURNで戻れないかと、GOSUBルーディンを階層にしたものを作って試してみましたが、10個までしか試していませんが、RETURNでちゃんと戻ってきているようでした。そこでメモリの上限までスタックは使えるのかテストしてみました。

ROBONOVA情報局WikiにSRAMのサイズは4KBで、アドレス領域が、0x0100 ー 0x10FFと書いてあるので、

IF sp<&h0D02 OR sp>=&h10FE THEN

として試してみました。
で、結果、変にはなりませんでした。音が鳴り止むまで長かった〜
ならば

IF
sp<&h0D02 OR sp>&h1110 THEN
    MUSIC "G"
 END
ENDIF

IF sp=&h0D04 THEN
    MUSIC "A"
    POKE &h04D5,&hFE
    POKE &h04D6,&h10
ENDIF

とサンプル4の一部分を書き換えて、上限を超えたらどうなるのかも試してみました。0x10FEまでは変にならなかったので、スタックポインタの値をPOKEを使ってメモリの上限にセットする式を加えました。結果、0x1110までやっても変にはなりませんでした。私にはもう分りません

殆ど、GOSUB...RETURNの話になってしまいましたが、メモリ内の様子を見たい時、どうしても変更させたい時にPEEK, POKEが使えます。ただし、PEEKはいいんですが、POKEは書換えなので、間違って書き換えたりしたら、とんでもないことが起こりえますので、十分注意して有効利用して下さい。

参考資料

  1. ROBOBASIC講座(GOSUB...RETURN)
  2. ROBOBASIC講座(PEEK、POKE その1)
  3. ROBOBASIC講座(テンプレートMAINループ)
  4. ROBONOVA情報局Wiki
  5. Robotics Files

|

« RZ1Basic v0.2.3 公開 | トップページ | RZ1Basic v0.2.3日本語Win版 »

ROBOBASIC講座」カテゴリの記事

コメント

こんばんは。
このプログラムが一見よさそうに動作するのは、GOTOだからではないでしょうか?
さらに簡略化して再帰呼び出しのプログラムを作って確認してみたところ、スタックポインタの参照先(スタック)の内容を見ていくと0x0E00で見事に壊れました。

投稿: avalon | 2008年2月23日 (土) 02時29分

ありがとうございます。
確かに参照先が正しいかのチェックを組み込んでいませんでした
検証ありがとうございます。とりあえずスタック領域は0x0D02から0x0DFFまで使えると思っていいんでしょうね

投稿: micono | 2008年2月23日 (土) 03時54分

ルールがよくわかりませんが、必ずしも使えるとは限らないようですね。プログラムによっては壊れます。

それから、ACTION命令ですが、中身は書かれている通り「RR=ACTION No+50 ; GOSUB メイン」なのでACTIONを実行するたびにスタックを1つ使っちゃいます。 当然繰り返せば使い尽くしてしまいますのでおかしな動作をすると思います。(そうするのも強引だと思いますがスタックポインタをリセットするようなことをしているのかと期待しましたが、普通のGOSUBでした。) サポートしている命令が第一変数の使い方といい、こんないい加減で中途半端な実装でいいのかと思ってしまいました(笑)
むしろ、GOTO メインの方がまだ害が少ない様に思います。

投稿: avalon | 2008年2月23日 (土) 09時01分

そうすると、やっぱりマニュアルにある5回までというのを信じておいた方がいいんでしょうかね?

ほんといい加減で中途半端な実装でいいのかと思います。

RZ1Basicにいろいろ便利な独自のコマンドを作ろうかと思ったりもしますが、汎用性がなくなってしまうので作ってないです。ON ... GOSUBとか、ACTIONGOTO n とか、作ろうと思えば作れるんだけどねぇ〜〜

投稿: micono | 2008年2月23日 (土) 09時20分

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: ROBOBASIC講座(PEEK、POKE その2):

« RZ1Basic v0.2.3 公開 | トップページ | RZ1Basic v0.2.3日本語Win版 »