サブルーチンはアルゴリズムのところで
解説しているので、サブルーチンが何かはここでは省略する。
どこから呼ばれるかわからないサブルーチンでは、戻るアドレスも変わるので、
「JMP」命令を使用することはできない。(できなくはないんだけど)
そこでこのような用途には「CALL」と「RET」を用いる。命令から推測できるように、
「CALL」でサブルーチンにジャンプし、「RET」で元の場所に戻ってくる。
元の場所に戻ってくるということは、どこかにアドレスを保存しておかなくては
ならない。そのようなレジスタはないのだから、どこかのメモリーに置かれている
わけである。これはスタックセグメント(SS)のスタックポインタ(SP)が指す
領域に保管されている。(ちょっと違うけど)
まず、「CALL」命令が実行されると、SPを2減らす。次に戻ってくるアドレス
(CALL命令の次の命令があるアドレス)をSS:SPに保管する。そして、CALL命令のオペランド
が指すアドレスにジャンプする
イメージ的には次のような感じである
sub sp,2
mov [ss:sp],ip
jmp ADDRESS
|
逆に「RET」命令では、SS:SPが指す2byte(16bit)の内容のアドレスにジャンプし、
SPを2増やす。
下記に例を示した。
START:
mov dl,'0'
call DISP
inc dl
call DISP
inc dl
call DISP
inc dl
call DISP
inc dl
mov ax,4c00h
int 21h
DISP:
mov ah,2
int 21h
ret
|
実行結果:「0123」と表示する。
さて、ジャンプ命令では「short jmp」、「near jmp」と「far jmp」があることは
すでに述べた。「CALL」も「near call」と「far call」がある。意味も書き方も同じで、
「call far [ds:1000]」のように書く。「near call」の書き方は上の例に示した
通りである。
また、サブルーチンから他のサブルーチンもしくは自分自身を呼び出しも可能で
ある(これはよくやる)。さらに、サブルーチンから他のサブルーチンへ
「jmp」したり、「jmp」で、メインプログラムに戻ってきても良いが、バグを防ぐ目的、
サブルーチンの汎用性といった問題から、お勧めしない。