1秒に何十億回もくり返す
スマホでゲームのアイコンをタップすると、プロセッサがゲームの命令を実行し始めます。その数は、1秒に何十億個にもなります。
1つ1つの命令は、「この2つの数を足す」のようにとても小さなものです。そして、どの命令も同じ3つの手順を通ります。今日は、その手順を1つずつ見ていきます。
このレッスンのゴール
メモ
フェッチ・デコード・実行のサイクルを追うことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 命令 | プロセッサができる、小さな1つの手順 | add a0, a0, a1 |
| メモリアドレス | メモリの中の1つの場所の番号 | |
| レジスタ | プロセッサの中にある、小さくて速い記憶場所 | a0 |
| プログラムカウンタ | 次の命令のアドレスを持っているレジスタ | |
| アセンブリ言語 | プロセッサの命令を短い英単語で書いたもの | |
| サイクル | 同じ手順を何度もくり返すこと |
学生が入力するセルは、このプレビューでは空白です。
プロセッサの中にあるもの
プログラムは、命令の並びとしてメモリの中で待っています。1つ1つの命令に、それぞれのメモリアドレスがあります。
プロセッサには、命令を読んで何をするか決める制御装置があります。前回のゲートで作られ、足し算や比べることをする演算装置(ALU)もあります。そして、作業中の数を入れておく小さな記憶場所、レジスタがあります。
部品とその役割
| 部品 | 役割 |
|---|---|
| メモリ | プログラムとデータを入れておく |
| プログラムカウンタ | 次の命令のアドレスを持つ |
| 制御装置 | 命令が何を意味するか読み取る |
| 演算装置(ALU) | 足し算、引き算、論理の計算をする |
| a0 や a1 などのレジスタ | 作業中の数を入れておく |
学生が入力するセルは、このプレビューでは空白です。
フェッチ、デコード、実行、またフェッチ
フェッチ: プロセッサは、プログラムカウンタが指すアドレスの命令を取り出します。プログラムカウンタは、次のアドレスに進みます。
デコード: 制御装置が、その命令が何を求めているかを読み取ります。実行: プロセッサがそれを行います。たとえば、演算装置が2つのレジスタを足します。そして、またフェッチから始まります。
始める前に
メモ
上のバーの Start the lab を押し、マシンが動き出すまで待ってください。これから読むプログラムは、RISC-V というプロセッサ用です。ラボのマシンは RISC-V ではないので、エミュレータで動かします。
arch フォルダへ移る
cd ~/archここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
5つの命令のプログラムを読む
cat add.sここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
命令を機械語にする
riscv64-linux-gnu-as add.s -o add.oここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
実行できるプログラムにする
riscv64-linux-gnu-ld add.o -o addここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
命令とアドレスを見る
riscv64-linux-gnu-objdump -d addここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
例: プログラムを1命令ずつ追う
| プログラムカウンタ | 命令 | 実行で起きること | a0 | a1 |
|---|---|---|---|---|
| 100b0 | li a0,2 | a0 に2を入れる | 2 | ? |
| 100b4 | li a1,3 | a1 に3を入れる | 2 | 3 |
| 100b8 | add a0,a0,a1 | 演算装置が足して a0 に入れる | 5 | 3 |
| 100bc | li a7,93 | プログラムを終える呼び出しを選ぶ | 5 | 3 |
| 100c0 | ecall | a0 をステータスにして終了を Linux に頼む | 5 | 3 |
学生が入力するセルは、このプレビューでは空白です。
よくある間違い
注意
プログラムカウンタは、実行した命令の数を数えていると考える人がよくいます。持っているのは、次の命令のアドレスです。ここでは命令が4バイトなので、4ずつ増えます。ジャンプ命令があると、そこに新しいアドレスが入ります。
2を7に変えたコピーを作る
sed 's/a0, 2/a0, 7/' add.s > seven.sここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コピーを機械語にする
riscv64-linux-gnu-as seven.s -o seven.oここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コピーをリンクする
riscv64-linux-gnu-ld seven.o -o sevenここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
予想してからエミュレータで動かす
qemu-riscv64 ./sevenここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
残した答えを読む
echo $?ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: プログラムカウンタを見る
Open terminal を押し、gcc -O2 -o loop loop.c で loop を作ってから gdb ./loop と打ちます。続けて break main、run と打ちます。
info registers pc でプログラムカウンタが見えます。stepi で1命令だけ実行し、もう一度 pc を見てください。いくつ進みましたか。終わるときは quit のあと y です。