クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

論理ゲートで足し算の回路を作る(加算器)

このレッスンのあとで: 論理ゲートを組み合わせて、加算器を作ることができる。

55分のレッスンコマンド8件コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

数えられない部品で計算する

自動販売機は、入れた100円玉と50円玉を一瞬で足して、150円と表示します。けれど、中のプロセッサの部品は、どれも数を数えられません。

1つ1つの部品は、2つのビットについて「はい」か「いいえ」を答えるだけです。今日は、その答えを組み合わせて足し算を作ります。

このレッスンのゴール

メモ

論理ゲートを組み合わせて、加算器を作ることができる。

キーワード

ことばいみれい
論理ゲート1つか2つの入力ビットから、1つの出力ビットを作る回路
真理値表すべての入力と、そのときの出力を並べた表
桁上がり和が大きすぎるとき、次のけたへ送る1ビットキャリー
半加算器2つのビットを足す、ゲート2つの回路
全加算器2つのビットと桁上がりを足す回路
オーバーフロー答えが、決まったビット数に入りきらないこと

学生が入力するセルは、このプレビューでは空白です。

4つのゲートが、ビットに答える

論理ゲートは、ビットを受け取って1ビットを返します。AND は、両方が1のときだけ1です。OR は、どちらかが1なら1です。XOR(排他的論理和)は、2つが違うときに1です。NOT は入力が1つで、それを反対にします。

真理値表は、すべての入力と出力を並べた表です。入力が2つなら場合は4つだけなので、表は短くなります。

真理値表: 3つのゲート

ABA AND BA OR BA XOR B
00000
01011
10011
11110

学生が入力するセルは、このプレビューでは空白です。

アーキテクチャのフォルダへ移る

コマンド
cd ~/arch

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

12 と 10 にゲートを当てる

コマンド
python3 -c "print(12 & 10, 12 | 10, 12 ^ 10)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

例: ビットごとに見たゲート

ビット10進数
A110012
B101010
A AND B10008
A OR B111014
A XOR B01106

学生が入力するセルは、このプレビューでは空白です。

ゲート2つで、2ビットを足す

2つのビットの足し算は、4通りです。0 + 0 は0、0 + 1 と 1 + 0 は1です。ところが 1 + 1 は2で、2進数では 10 と書きます。

答えの右のビットは A XOR B です。左のビット、つまり桁上がりは A AND B です。XOR ゲート1つと AND ゲート1つで、半加算器ができます。

真理値表: 半加算器

AB和(XOR)桁上がり(AND)
0000
0110
1010
1101

学生が入力するセルは、このプレビューでは空白です。

XOR は、桁上がりを無視した和

コマンド
python3 -c "print(12 + 10, 12 ^ 10, (12 & 10) << 1)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

全加算器は、桁上がりも受け取る

いちばん右以外のけたは、右のけたから来た桁上がりも足す必要があります。つまり、3つのビットを足します。

全加算器は、半加算器2つと OR ゲート1つでこれを行います。4つつなげば、4ビットの数を足せます。桁上がりは右から左へ、波が伝わるように順に送られます。そのため、これをリップルキャリー加算器と呼びます。

例: 0101 + 0011 を右から

けたAB入る桁上がり和出る桁上がり
1の位11001
2の位01101
4の位10101
8の位00110

学生が入力するセルは、このプレビューでは空白です。

答えが入りきらないとき

加算器が残すビット数は決まっています。符号なしの数では、最上位から出た桁上がりは捨てられ、答えは0の側へ一周します。

符号付きの数では、見方が違います。0101 + 0011 は8ですが、4ビットの2の補数では 1000 は -8 と読まれます。正の数どうしを足して、負の答えになりました。最上位から何も出ていなくても、これもオーバーフローです。

180 と 90 を足すプログラムを書く

コマンド
printf '.globl _start\n_start:\n  li a0, 180\n  li a1, 90\n  add a0, a0, a1\n  li a7, 93\n  ecall\n' > wrap.s

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

アセンブルする

コマンド
riscv64-linux-gnu-as wrap.s -o wrap.o

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

リンクする

コマンド
riscv64-linux-gnu-ld wrap.o -o wrap

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

エミュレータで実行する

コマンド
qemu-riscv64 ./wrap

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

終了ステータスを読む

コマンド
echo $?

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

「オーバーフローとは、最上位から桁上がりが出ることだ」と考える人が多くいます。それは符号なしの数のときだけです。2の補数では、1110 + 0011 は桁上がりが出ますが、-2 + 3 = 1 で答えは正しいです。符号付きのオーバーフローは、同じ符号の2数を足して、答えの符号が変わったときに起きます。

さらに挑戦

プロセッサには、引き算専用の回路がありません。a - b を、a + (NOT b) + 1 として計算します。2の補数では、NOT b + 1 が -b になるからです。

課題の add_bits を使って subtract_bits(a, b) を書いてください。b の全ビットを反転して a に足し、さらに 0001 を足します。0110 - 0010 と 0010 - 0110 を試し、2回目の足し算を回路でどう省けるか考えましょう。

このラボとソースについて: コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。