サブルーチン
コールとリターン
プログラムが大きくなってくると、同じようなコードを何度も繰り返します
似たようなプログラムを何度も使いまわす時、何度も書きなおすのは不合理です
C言語プログラマであれば、この場合は関数での処理を思い出すでしょう
まさにそれが正解ですが、機械語では関数というものは存在しません
機械語ではこれをサブルーチンと呼び、呼び出し場所に戻る機能をサポートしています
因みに、エントリポイントからのプログラムをサブルーチンに対しメインルーチンと呼びます
サブルーチンの概念はBasicプログラマーさんならばよくご存知でしょう
機械語では、指定オフセットアドレスにジャンプし処理を終了すると呼び出し元に戻ります
呼び出した場所に戻ることができるJMP命令のようなものです
サブルーチンの先頭となるオフセットアドレスに移動するにはCALL命令を使います
第一オペランドに、オフセットアドレスまたはそれを表すレジスタ、メモリアドレスを指定します
CALLした場合は、必ず呼び出し元へ戻る必要があります
そうでなければ、永遠とサブルーチンを走っていることになります
サブルーチンから呼び出し元へ戻るには、サブルーチンでRETを指示します
-A 200
15F2:0200 MOV WORD PTR [BX] , AX
15F2:0202 ADD BX , 2
15F2:0205 RET
15F2:0206
-A 100
15F2:0100 MOV AX , 4241
15F2:0103 MOV BX , 300
15F2:0106 CALL 200
15F2:0109 MOV AX , 4443
15F2:010C CALL 200
15F2:010F
-G =100 10F
AX=4443 BX=0304 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=010F NV UP EI PL NZ NA PO NC
-D 300 303
15F2:0300 41 42 43 44 ABCD
オフセットアドレス0200〜0205がサブルーチンとなっています
0106でCALLしてサブルーチンへとジャンプしますが、0205のRETで復帰し
その次の0109からプログラムを実行します
サブルーチンはその後、010Cでも呼び出しています
このように、メインルーチンから何度もサブルーチンを呼び出すことができます
このサブルーチンは、AXレジスタをBXレジスタの指すアドレスへストアします
そして、最後にBXレジスタの内容に2を加算して戻ります
さらに、サブルーチンのサブルーチンというものも可能です
サブルーチンからコールされたサブルーチンもちゃんと呼び出し元に復帰します
-A 300
15F2:0300 MOV DL , FF
15F2:0302 RET
15F2:0303
-A 200
15F2:0200 MOV DH , EE
15F2:0202 CALL 300
15F2:0205 RET
15F2:0206
-A 100
15F2:0100 CALL 200
15F2:0103 MOV AX , DX
15F2:0105
-G =100 105
AX=EEFF BX=0000 CX=0000 DX=EEFF SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0105 NV UP EI PL NZ NA PO NC
サブルーチンである0202でCALLしています
するとサブルーチンのサブルーチンが実行され、RETでサブルーチンに復帰します
このように、サブルーチンはネスティング(入れ子構造)が可能です