メモリ: ロードとストア

メモリ: ロードとストア

メモリは番号付きの記憶スロットが大きく並んだもので、各スロットは1つのバイト(8ビット)を保持します。スロットの番号はそのアドレスです。レジスタはCPUが持つ高速なスロットの小さな集合です。メモリははるかに大きいですが遅く、レジスタに収まらないものすべて(配列や文字列など)を保持します。メモリ内の値を扱うには、それをレジスタにロードし、変更し、再びストアします。

レジスタは少なく、メモリは大きいです。(load word)はワードをメモリからレジスタにコピーし、(store word)はそれを戻します。アドレスはoffset(register)と書きます。

RISC-Vのメモリはバイトアドレス方式なので、各バイトは順番に独自のアドレスを持ちます。ワードは32ビット、つまり4バイトなので、次のワードに到達するにはメモリポインタを4進めます。これが配列のオフセットが0、4、8、…となる理由です。実ハードウェアでは、4の倍数でないアドレスからワードをロードすると遅くなったりトラップが発生したりすることがあります。このシミュレータでは許可されていますが、ワードを4バイトに整列させる習慣を身につけるべきです。

形状のロード/ストア
lw t0, 0(a1) # t0 = アドレスa1のメモリ
sw t0, 4(a1) # アドレスa1+4のメモリ = t0

offset(register)では、レジスタに保持されたアドレスに小さなオフセット数が加算されます。0(a1)はa1自体のアドレスであり、4(a1)はそこから4バイト先です。これにより、ベースレジスタを変更せずに近くの値に到達できます。

メモリに保存中
CPU
li t0, 0x11111111
li t1, 0x22222222
li a0, 0x1000
sw t0, 0(a0)
sw t1, 8(a0)
Registers
t00x00000000
t10x00000000
a00x00000000
Random Access Memory (RAM)
AddressValue
0x100C0x00000000
0x10080x00000000
0x10040x00000000
0x1000
0x00000000
0x0FFC0x00000000

レジスタとメモリはゼロから始まります。

アニメーションでは、ベースレジスタa0は変わりません。命令に書かれたリテラルのオフセットだけが増加し、次の対象メモリアドレスへ移動します。 このパターンに一致するメモリを作成するには、データセクションで.word(1つ以上の32ビット値)または.space N(N個の空白バイト)を使って名前付きメモリを確保します。各ワードは4バイトなので、連続する項目はオフセット0、4、8に位置し、これらはストア命令で使うのと同じ数値です。

データセクションで名前付きメモリを確保するには、.word(1つ以上の32ビット値)または.space N(N個の空白バイト)を使います。各ワードは4バイトを占めるので、連続する項目はオフセット0、4、8などに位置します。

メモリ内の配列を合計する
.data
nums: .word 10, 20, 30, 40 # 4ワード
.text
la t1, nums # t1 = 配列のアドレス
li t2, 4 # 個数
li t0, 0 # 累計
loop:
beq t2, zero, done
lw t3, 0(t1) # 現在の要素を読み込む
add t0, t0, t3 # 合計に加える
addi t1, t1, 4 # 次のワードへ進む (4バイト)
addi t2, t2, -1 # 残り1つ減る
j loop
done:
mv a0, t0 # 合計を出力 (100)
li a7, 1
ecall
li a7, 10
ecall

は配列のアドレスをt1に入れ、t2は残り4つの要素を数え、t0は実行中の合計を保持します。各パスで、は要素が残っていないときにループを停止します。はt1が指す要素をロードし、はそれを合計に加算し、はポインタを1ワード進め、はカウントを減らします。4つの要素すべて(10 + 20 + 30 + 40)の後、doneは100を出力します。

💡
シミュレータのツールバーにあるHEX/DECトグルを使って、アドレスと値の表示方法を切り替えます。現在のステップを追いやすくする方の基数を選んでください。