ちょっと疲れてきました。「サブルーチン」って、きょうび、プログラムを学んだ人でも知らないかもしれませんね。「プロシージャ」とか「関数」とか「クラス」って言ったほうが通じるかもしれません。平たく言うとプログラムの寄り道です。動作としては。寄り道が終わったら元の道に帰ることが必要になります。何のための寄り道か。「ルーチン」ですから、「いつもの退屈なアレ」をやるための寄り道です。
一続きのプログラムを作成している中で、「同じようなまとまった処理」がいくつも出てくる場面に遭遇することは必定です。これを本筋のプログラムとは離れた場所に書いておいて、本筋のプログラムから何度でも「寄り道」して使うことができます。その「同じようなまとまった処理」をサブルーチンと呼び、そこに寄り道することをサブルーチンを「呼び出す」と表現します。
サブルーチンに寄り道する際はジャンプするだけではだめで、必ず帰ってくる場所(リターンアドレス)を覚えておかなくてはなりません。リターンアドレスを格納するのにスタックを用います。スタックの動作はこちらで説明しています。リターンアドレスは次の命令の場所すなわちプログラムカウンタ(PC)に入っていますので、PCの値をスタックにプッシュしてから寄り道先にジャンプします。
寄り道が終わったら本筋のプログラムに帰るため、スタックからリターンアドレスをポップしてPCにセットします。
スタックを使っているおかげでサブルーチンからさらに別のサブルーチンに寄り道することも可能となります。これが”nesting”「入れ子構造」と言われるものです。
Operation | Mnemonic | inCode | Opr2 | Opr3 | Opr4 | Opr5 | #bytes | Opcode | Ie | Cy | Cd |
---|---|---|---|---|---|---|---|---|---|---|---|
push PC then PC <- (PC) | CALL | addr | addr | 3 | 63 aa aa | ||||||
pop PC | RET | 1 | 65 |
Opcode欄の「aa aa」に寄り道先=サブルーチンの先頭アドレスを指定してください。
コーディング例
Addr | Data | Label | Opcode | Operand | Comment | ||||
---|---|---|---|---|---|---|---|---|---|
0000 | 30 | 03 | start: | LDI.b | 03 | ||||
0002 | 63 | 08 | 00 | CALL | routine | ラベル”routine:”の0800番地を呼び出す アドレス0005をスタックにプッシュし 0800番地にジャンプする |
|||
0005 | 31 | 32 | 00 | LDI.w | 3200 | ||||
0008 | 63 | 08 | 00 | CALL | routine | 再び”routine:”を呼び出す アドレス0011をスタックにプッシュし 0800番地にジャンプする |
|||
0011 | 31 | 22 | 22 | LDI.w | 2222 | ||||
0014 | 63 | 08 | 00 | CALL | routine | もう一度”routine:”を呼び出す アドレス0017をスタックにプッシュし 0800番地にジャンプする |
|||
0017 | 99 | HALT | |||||||
: : |
|||||||||
0800 | 39 | 00 | routine: | OUT | 00 | (ここがサブルーチンの入り口) | |||
0802 | 65 | RET | 呼び出しの次の命令に帰る スタックからポップしたアドレスにジャンプする |
補足
- “RET”は”Return”(リターン)の略です。
- 飛び先はプログラム領域の範囲内に限るべきです。
- スタックにPCの値をプッシュする際は、実際には2バイト分の0000を上位に連結した値が使われます。これはスタックが4バイト単位に増減するようにできているためです。
- この命令はステータスレジスタ(SR)を変化させません。