もしもプログラムが順次実行だけだったら、すごくつまらないです。というわけで今回は分岐を扱いたいと思います。
いつでも分岐する分岐を「無条件分岐」といいます。ジャンプとも呼びますが、とりあえずはこれを使ってみましょう。命令は、CSファイルを逆アセンブルして調べても良いですが、私たちは命令表を手に入れたのでそちらを見ながら考えましょう。
無条件分岐はジャンプです。ということなので「jump」「jmp」という命令をさがしてみます。しかし、なんかmethodとかとついていたりで目的のものではなさそうです。予想が外れました。というわけで「分岐」を英語に直したものである「branch」でさがしてみます。
見つけられたでしょうか?正解は「br.<length> br. – unconditional branch」です。「br」とずいぶん短くなっていますが、説明は「unconditional」つまり「無条件の」という意味になっているのでこれが正解です。
前にも説明しましたが、「~:」と書くとラベルになります。分岐先に指定します。
.assembly extern mscorlib{}
.assembly branchtest{}
.method public static void main() cil managed
{
.entrypoint
.maxstack 1
ldc.i4 200
call void [mscorlib]System.Console::
WriteLine(int32)
br end
//下が実行されない
ldc.i4 100
call void [mscorlib]System.Console::
WriteLine(int32)
end:
ret
}
実行すると、「100」を出力して終わります。また、brはオフセットを指定するため、数字で指定することも出来ます。
.assembly extern mscorlib{}
.assembly branchtest{}
.method public static void main() cil managed
{
.entrypoint
.maxstack 1
ldc.i4 200
call void [mscorlib]System.Console::
WriteLine(int32)
br 10 //10バイト後に飛ぶ
//下が実行されない
ldc.i4 100
call void [mscorlib]System.Console::
WriteLine(int32)
ret
}
大抵は使わないと思います。それと、今までと同じ系統で、「br.s」というものもあります。1バイトのオフセットが指定できるので、「-128~127」の範囲のジャンプで在ればこちらを使った方が少ないバイト数になります。
.assembly extern mscorlib{}
.assembly branchtest{}
.method public static void main() cil managed
{
.entrypoint
.maxstack 1
ldc.i4 200
call void [mscorlib]System.Console::
WriteLine(int32)
br.s end
//下が実行されない
ldc.i4 100
call void [mscorlib]System.Console::
WriteLine(int32)
end:
ret
}
3バイト分の節約になります。