メモリ: ロードとストア
メモリは番号付きの記憶スロットが大きく並んだもので、各スロットは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バイト先です。これにより、ベースレジスタを変更せずに近くの値に到達できます。
| Address | Value |
|---|---|
| 0x100C | 0x00000000 |
| 0x1008 | 0x00000000 |
| 0x1004 | 0x00000000 |
| 0x1000 | 0x00000000 |
| 0x0FFC | 0x00000000 |
レジスタとメモリはゼロから始まります。
a0は変わりません。命令に書かれたリテラルのオフセットだけが増加し、次の対象メモリアドレスへ移動します。
このパターンに一致するメモリを作成するには、データセクションで.word(1つ以上の32ビット値)または.space N(N個の空白バイト)を使って名前付きメモリを確保します。各ワードは4バイトなので、連続する項目はオフセット0、4、8に位置し、これらはストア命令で使うのと同じ数値です。データセクションで名前付きメモリを確保するには、.word(1つ以上の32ビット値)または.space N(N個の空白バイト)を使います。各ワードは4バイトを占めるので、連続する項目はオフセット0、4、8などに位置します。
.datanums: .word 10, 20, 30, 40 # 4ワード.textla t1, nums # t1 = 配列のアドレスli t2, 4 # 個数li t0, 0 # 累計loop:beq t2, zero, donelw t3, 0(t1) # 現在の要素を読み込むadd t0, t0, t3 # 合計に加えるaddi t1, t1, 4 # 次のワードへ進む (4バイト)addi t2, t2, -1 # 残り1つ減るj loopdone:mv a0, t0 # 合計を出力 (100)li a7, 1ecallli a7, 10ecall
は配列のアドレスをt1に入れ、t2は残り4つの要素を数え、t0は実行中の合計を保持します。各パスで、は要素が残っていないときにループを停止します。はt1が指す要素をロードし、はそれを合計に加算し、はポインタを1ワード進め、はカウントを減らします。4つの要素すべて(10 + 20 + 30 + 40)の後、doneは100を出力します。
