実行順序の変更
無条件ジャンプ
これまでのプログラムは、指定アドレスから順番に実行するだけでした
ここでは、プログラムの流れを変える方法を覚えましょう
CPUはどのようにプログラムを実行しているかというとIPレジスタを用いています
プログラムは常に現在IPレジスタが指すオフセットアドレスを実行します
//セグメントはCSレジスタなので CS : IP が実行アドレスとなる
逆に考えれば、このIPレジスタを制御することがプログラムの制御につながるのです
しかし、IPレジスタのコントロールはMOV命令を使うことはできません
IPレジスタを書きかえるには、専用の命令を使わなくてはならないのです
ジャンプ命令には「条件ジャンプ」と「無条件ジャンプ」が存在します
高級言語などでは、無条件のジャンプはいわゆる「GoToレス」の概念から
Java言語のように最初から実装していない言語もありますが
アセンブリのような低水準言語では、オフセットアドレスを指定してジャンプすることができます
無条件ジャンプを行うにはJMP命令を用います
ディスティネーションオペランドには、オフセットアドレスを指定するか
16ビットのレジスタまたはメモリ空間を指定します
JMP命令が実行されると、無条件に指定したアドレスへジャンプします
-A 100
15F2:0100 MOV AX , 100
15F2:0103 MOV BX , 200
15F2:0106 JMP BX
15F2:0108
-A 200
15F2:0200 MUL BX
15F2:0202
-G =100 202
AX=0000 BX=0200 CX=0000 DX=0002 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0202 OV UP EI PL NZ AC PO CY
オフセットアドレス 0106 が実行されると、IPレジスタは 200 にセットされます
終了時にIPレジスタが202になっていることが確認できますね
疑わしければ、トレースして確認しても良いでしょう
プログラムはJMP命令でアドレス200へジャンプしてMULを実行しています
16進数100×200は20000なので、DXレジスタとAXレジスタを見ればわかりますね
このように、同じCS内部のジャンプをセグメント内ジャンプ
またはnearジャンプと呼びます
さらにJMP命令は、即値でのアドレス指定も可能です
-A 100
15F2:0100 JMP 110
15F2:0102
-A 110
15F2:0110 MOV AX , 100
15F2:0113 ADD AX , FF
15F2:0116
-G =100 116
AX=01FF BX=0200 CX=0000 DX=0002 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0116 NV UP EI PL NZ NA PE NC
これらの動作では決してCSレジスタは変更されません
また、このようにIPアドレスから-128〜127以内でのnearジャンプのことを
特別にshortジャンプと呼びます //機械語レベルで分別されています
JMP SHORT オフセットアドレス
と指定することで、ショートジャンプであることを明示します
この方がプログラムのサイズは小さくなりますが、ジャンプ範囲が小さいことに注意してください
絶対アドレス指定と相対アドレス指定
アセンブリ言語では、ジャンプ命令のアドレス指定は絶対アドレスです
つまり、直接ジャンプ先のアドレスを指定します
これに対し、機械語は相対アドレスで指定しなければなりません
レジスタやメモリからジャンプアドレスをロードする場合は絶対アドレスですが
即値による指定を行う場合、現在のIPレジスタの次の命令からの距離を相対的に指定します
-A 100
15F2:0100 JMP 102
15F2:0102 JMP 106
15F2:0104
-U 100 103
15F2:0100 EB00 JMP 0102
15F2:0102 EB02 JMP 0106
shortジャンプ命令は EB です
その後に1バイトの相対アドレスを指定します
EB00は、現在のアドレスから0距離進んだ場所(つまり単純に次の命令)
EB02は、現在のアドレスから2アドレス進んだ場所ということになります