数学をする

数学をする

すべての計算はレジスタ間で行われます。算術命令は最初に宛先を指定し、その後に読み取る2つのソースが続きます: は dest = src1 + src2 を意味します。

算術演算
t2, t0, t1←add
t0 = 7t1 = 5+t2 = 12

t2に場所 t0 と t1 を追加する。

左から入ってくる2本の線は t0 と t1 で、常にこの順序です。実行される演算が加算、減算、乗算、除算、剰余のいずれであっても、同じ形で入ってきます。2つの値が入り、1つの演算が行われ、1つの結果が右側の t2 に出てきます。 が最初に t2 を指定するのは、そこに結果が格納されるからであり、これはこのレッスンのすべての算術命令が従う唯一の順序規則と一致します。

足し算と引き算

は2つのレジスタに保持された数値を取り、その和を3つ目のレジスタに格納します。 は減算について同じことを行います: は t0 - t1 を計算します。どちらの命令もレジスタからのみ読み取ります。

算数の登録
add t2, t0, t1 # t2 = t0 + t1
sub t2, t0, t1 # t2 = t0 - t1

知っておくべきこと:レジスタは32ビットしか保持できないため、上限があります。結果が大きすぎて収まらない場合でも、エラーは発生しません。値は静かにラップアラウンドして非常に小さな数値になり、実行は続行されます。日常的な値がこの限界に達することはありませんが、上限について知っておく価値はあります。

2つ目のレジスタの代わりに固定数値を使うには、即値を意味する文字 i を追加します: は定数1を加算します。subi は存在しないため、定数を減算するには負の値を加算します:。

💡
は定数を加算します。 は2つのレジスタを加算します。この2つを混同することが初心者に最も多い誤りです。

掛け算と割り算

は2つのレジスタを乗算します。 はそれらを整数として除算し、端数を切り捨てるため、7 / 2 は 3 になります。 は剰余を返すため、7 % 2 は 1 になります。除算がクラッシュを引き起こすことはありません。ゼロで除算すると -1 が返されます。

掛け算、割り算、余り
mul t2, t0, t1 # t2 = t0 * t1
div t2, t0, t1 # t2 = t0 / t1 (整数)
rem t2, t0, t1 # t2 = t0 % t1 (余り)

まとめ

2つの数を足して表示する
li t0, 7
li t1, 5
add t1, t0, t1 # t1 = 7 + 5 = 12
mv a0, t1 # 出力サービスはa0を読む
li a7, 1
ecall
li a7, 10
ecall

は7をt0にロードします。 は5をt1にロードします。 はそれらを加算し、12をt1に書き込みます。 は結果をa0にコピーします。これは、printサービスが常にa0から値を読み取るためです。次に がprint-integerサービスを選択し、 がそれを実行します。最後に、 と がプログラムを終了します。

おまけ:シフトを用いた乗算

因数が2の累乗である場合、 よりも高速な方法が存在します。(論理左シフト)はレジスタのビットを左に移動し、シフトする各位置が値を2倍にします:1シフトで2倍、2で4倍、3で8倍。シフトは乗算よりもコストが低いため、コンパイラは頻繁にこれを使用します。

シフト操作を使用して8倍する
li t0, 5 # 5から始める
# 左に3ビットシフト (5 * 2^3 = 5 * 8)
sll a0, t0, 3 # a0 = 40
li a7, 1 # 整数を出力
ecall
li a7, 10
ecall

は5をt0に入れます。 はそのビットを3桁左にシフトします。各桁が値を2倍にするため、5は3回2倍され(5、10、20、40)、a0に40が得られます。残りは以前のprintパターンに従います。3を1や2に変えて、実行する前に結果を予測してみてください。

シフトによる乗算
5sll a0, t0, 0
×2 →
10sll a0, t0, 1
×2 →
20sll a0, t0, 2
×2 →
40sll a0, t0, 3
0
0
0
0
0
1
0
1

5を0ビット左にシフトしても5のままです。

8つのボックスはその上の数値の2進形式で、それぞれ1ビットであり、通常どおり左から右に読み取ります。行全体を1位置左にシフトすることは2を掛けることと同じ操作です。なぜなら、任意の基数で数字を1桁左に移動するとその値がその基数倍になるからです。2進数には2つの数字しかないため、乗数は2です。3回シフトするとこれが複合して8倍の乗算になり、これは が数値5に対して行うことと一致します。