今まで覚えたのは、命令「call」「ldstr」「ldc.i4」「ret」と、宣言「.entrypoint」「.maxstack」です。今回はこれらに加えて、足す・引く・掛ける・割る・あまり算・2の補数の命令を学びます。
とりあえず足し算です。命令は「add」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 2 ldc.i4 4 ldc.i4 5 add call void [mscorlib]System.Console::WriteLine(int32) ret }
たったこれだけです。「add」は引数として二つの数を取ります。そして、結果をスタックに戻します。応用で掛け算です。命令は「mul」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 2 ldc.i4 4 ldc.i4 5 mul call void [mscorlib]System.Console::WriteLine(int32) ret }
掛け算は「mul」です。
引き算、割り算、あまり算はスタックにデータを積む順番が重要になってきます。まずは引き算、命令は「sub」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 2 ldc.i4 4 ldc.i4 5 sub call void [mscorlib]System.Console::WriteLine(int32) ret }
引き算は「sub」です。この答えは「-1」になります。つまり、「先-後」が結果となるわけです。応用で割り算。命令は「div」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 2 ldc.i4 4 ldc.i4 5 div call void [mscorlib]System.Console::WriteLine(int32) ret }
割り算の答えは0方向へ丸められた結果になります。こちらも「先÷後」になっています。
同じ要用でもう一個。余り算です。これは割っていった時の余りを求める演算です。C言語では「%」でおなじみです。命令は「rem」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 2 ldc.i4 8 ldc.i4 3 rem call void [mscorlib]System.Console::WriteLine(int32) ret }
その値に-をつけた時の値を求めます。内部的にはnotして1足しています。この演算は1つの引数しかとりません。命令は「neg」です。
.assembly hina{} .method public static void main(){ .entrypoint .maxstack 1 ldc.i4 8 neg call void [mscorlib]System.Console::WriteLine(int32) ret }
これらの計算はオーバーフローを起こしてもそのまま演算を続けます。何もしません。淡々と、法則に従い計算しint32型の結果を返します。ILにはオーバーフローを教えてくれる命令もあります。しかし、それはまた後にしましょう。教えてもらっても今の状態では活用できないからです。
divとremは0割る側の数を0にすると0除算例外(DivideByZeroException)が発生します。起こさないように気をつけましょう。もちろん後には例外をキャッチして活用できるように組むことも出来るようになります。
次回は、ローカル変数をかじります。