分岐命令

プログラム実行の流れを変更するために、分岐命令が用意されています。この命令が実行されると、オペランドで示されるアドレスが IP レジスタにセットされ、そのアドレスから実行が再開されます。

分岐命令の種類

分岐命令には、次の種類があります。

無条件ジャンプ命令は、プログラムの実行地点を無条件に移動します。

条件ジャンプ命令は、ある条件が成立している場合にのみプログラムの実行地点を移動します。

サブルーチンコール(CALL)命令は、プログラムの実行地点を無条件に移動しますが、分岐元のアドレスをスタックに記憶しており、RET 命令が実行されると分岐元に戻ります。

プログラムの流れを移動する命令には、これらの他にソフトウェア割り込み(INT)命令があります。INT 命令はサブルーチンコールに似ていますが、分岐先の指定には番号を使用し、その番号で参照される割り込みベクタ(メモリ最下位部分に存在する)によって分岐先を決定します。また、INT 命令はフラグレジスタ値もスタックに記憶します。INT 命令による分岐先から戻るには IRET 命令を使用します。MS-DOS のシステムコールはこのソフトウェア割り込みによって行うようになっています。

条件ジャンプ命令における条件判定の方法

条件ジャンプ命令は、ある条件が成立している場合にのみジャンプを行う命令ですが、この条件の判定はフラグレジスタ(FLAGS)の値によって行います。

フラグレジスタは個々に意味を持つ 1 ビットフラグの集合になっており、CMP 命令や ADD 命令など、多くの命令ではその実行結果によってフラグレジスタの各ビットが設定されます。条件ジャンプ命令の条件判定はこのフラグレジスタの値によって決定します。

分岐命令のオペランドタイプ

分岐命令は 1 つのメモリオペランドを取り、それによって分岐先を指定します。オペランドのタイプによって分岐の方法が異なります。次に分岐命令で使用するタイプを示します。

SHORT タイプ

1 バイト自己相対分岐を行います。すなわち、符号付き 1 バイト数で表現されたオフセットだけ、プログラム実行アドレスを増減します。分岐先との距離は-128 バイトから+127 バイトでなければなりません。

NEAR タイプ

2 バイト自己相対分岐を行います。すなわち、符号付き 2 バイト数で表現されたオフセットだけ、プログラム実行アドレスを増減します。分岐先は現在と同じセグメント内になければなりません。

FAR タイプ

分岐先をセグメント:オフセット形式で指定します(絶対分岐)。このタイプの分岐ならば、分岐先がプログラムのどこにあっても到達可能ですが、SHORT や NEAR タイプの分岐に比べてコードサイズが大きく、実行速度も劣ります。

WORD タイプ

オペランドで指定されたメモリ値をオフセット値として、NEAR タイプのように現在のセグメント内へジャンプします(セグメント相対分岐)。

DWORD タイプ

16 ビットセグメントでは、指定されたメモリ値をセグメント:オフセットとして、FAR タイプのように絶対分岐を行います。始めの 2 バイトにオフセット値、後の 2 バイトにセグメント値が格納されている必要があります。

32 ビットセグメントでは、指定されたメモリ値を 32 ビットの:オフセット値としてセグメント相対分岐を行います。

FWORD タイプ

指定されたメモリ値をセグメント:オフセットとして、FAR32 タイプのように絶対分岐を行います。始めの 4 バイトにオフセット値、後の 2 バイトにセグメント値が格納されている必要があります。

分岐命令のオペランドにありうるタイプは以上ですべてですが、個々の分岐命令によっては指定できないタイプもあります。

SHORT、NEAR、FAR の各タイプの分岐は、機能的には似ていますが、その効率と汎用性に違いがあります。SHORT タイプの分岐は、コードサイズと実行速度の効率では最もすぐれているものの、分岐先が近くにない場合は使用できません。FAR タイプの分岐は最も不効率ですが、プログラム内のどこへでも分岐可能です。

例    JMP    SHORT L
    JMP    NEAR PTR L
    JMP    FAR PTR L
    JA    L
    CALL    L
    INT    21h

T1    DW    OFFSET L
    JMP    WORD PTR T1

T2    DW    SEG L, OFFSET L
    JMP    DWORD PTR T2

ジャンプ先アドレスの絶対指定LASM

V2.09 以降では、JMP および CALL 命令でジャンプ先のアドレスを絶対指定できるようになりました。

次のような指定が可能です。



1<命令> <数値>:<数値>

2<命令> <セグメント名>:<数値>

3<命令> <数値>

1.    JMP    8000h:0020h
2.    JMP    CODE:0020h
3.    JMP    0020h
4.    JMP    8000h:LABEL1

1. のコードは、セグメント 8000h +オフセット 20h への FAR ジャンプです。
2. のコードは、セグメント CODE +オフセット 20h への FAR ジャンプです。
3. のコードは、現在のセグメント+オフセット 20h への自己相対 NEAR ジャンプです。
4. のコードは、セグメント 8000h +LABEL1 のオフセットへの FAR ジャンプです。

注意

3. のようにオフセット値だけを指定すると、NEAR タイプの自己相対ジャンプのコードが生成されます。この場合、ジャンプ先は現在アセンブル中のセグメント上の指定オフセットになります。そのセグメントが PUBLIC 属性を持ち、リンク時にほかのセグメントと連結される場合でも、ほかの連結セグメントは考慮されません。つまり、連結後のセグメント全体の先頭ではなく、現在アセンブル中のセグメント(の一部分)の先頭が基準になります。

[目次]