「天文屋のためのマイコン入門」サブルーチンについて考える
今日は、サブルーチンについて、もう少し考えて見たいと思います。
まず、最初に問いです。
サブルーチンの処理の中で別のサブルーチンを呼べるか?
この問いに私が答えを言うのは簡単です。でも、せっかくなので、サブルーチンの動作の仕組みを考えながら、上記問いの答えを考えてみたいと思います。
まず、サブルーチンコール命令を良く見てみます。
CALL ラベル
この命令によって、ラベルの番地にジャンプします。しかし、似たような命令がありました。
GOTO ラベル
これも、ラベルの番地にジャンプします。CALLもGOTOも動作が同じように見えます。どこが違うのでしょうか? CALLをGOTOに変えたらプログラムは動くでしょうか? 当然ですが、動きません。では違いはどこにあるのでしょうか?
その違いの鍵はサブルーチンから戻るRETURN命令にあります。
RETURN
この命令、番地の指定は一切ありません。それなのになぜ、元の番地に戻れるのでしょうか?
さらに、次のような場合を考えてみてください。メイン処理の中で、同じサブルーチンを2回呼ぶとします。
図を見れば分かるように、2回RETURN命令が実行されますが、まったく同じ番地の同じRETURN命令なのに、1回目と2回目で戻る番地が違うのです。
これはちょっと考えると不思議です。RETURN命令はどうして戻り先が分かるのか?
勘のいい人ならもうわかると思いますが、答えは、
CALL命令が戻り番地をどこかに保存しておいて、RETURN命令はそれを参照している。
その通りです。CALL命令は戻り番地はたやすく分かります。なぜなら、自分自身の番地+1が戻り番地だからです。それをどこかに保存してからラベルの番地へジャンプします。
CALL命令=戻り番地の保存+GOTO命令
と考えられます。ここで最初の問いに戻ります。
サブルーチンの処理の中で別のサブルーチンを呼べるか?
答えはNOということになります。理由はこうです。戻り番地の保存先がどこかにあるとします。それをBUFと呼ぶことにします。
1 MAINからSUB1をコールするとき、MAINの戻り番地がBUFに保存される
2 SUB1からSUB2をコールするとき、SUB1の戻り番地がBUFに保存される
この時点で、MAINの戻り番地が上書きされますので、SUB1からMAINに戻ることはできなくなります。
ただし、これは戻り番地を保存する場所が一つしかないとした場合です。もし2つあるなら答えはYESになります。
実は、保存する場所は8つあります。したがって、サブルーチンの中でサブルーチンを呼ぶことをネストするといいますが、ネストレベル8まで許されるということです。
9回目ネストすると、最初の保存場所が上書きされるので、もう最初の位置に戻ることはできません。
ここで勘違いして欲しくないのは、サブルーチンが8回までしかコールできないと言っているのではないです。また、サブルーチンは8個までしか定義できないと言っているのでもありません。
サブルーチンは何個でも定義できますし、何回でも呼ぶことができます。ただ、サブルーチンの中から別のサブルーチンを呼ぶネスト構造が8レベルまでということです。ロシアのマトリョーシカ人形は8個までということです。ここは勘違いしないように注意してください。
中級者向け補足(ここの説明がわからなかったら、それはそれでいいです)
ここで言うネストレベルとは、実際ににCALL命令が実行された場合の問題です。単にプログラム中にCALL命令があるだけでは判断できません。もし、条件判定などでこのCALL命令が実行されないなら、これはネストレベルの中に含まれません。このように実行時にきまる問題を動的な問題といいます。(反対は静的な問題)ネストレベルは動的な問題です。
| 固定リンク
コメント