Speicher: laden & speichern

Speicher: laden & speichern

Der Speicher ist eine große Reihe nummerierter Speicherplätze, und jeder Platz enthält ein Byte (8 Bits). Die Nummer eines Platzes ist seine Adresse. Register sind die kleine Menge schneller Plätze der CPU. Der Speicher ist viel größer, aber langsamer, und er enthält alles, was nicht in Register passt, wie Arrays und Strings. Um mit einem Wert im Speicher zu arbeiten, lädt man ihn in ein Register, ändert ihn und speichert ihn zurück.

Es gibt wenige Register und der Speicher ist groß. (load word) kopiert ein Wort aus dem Speicher in ein Register, und (store word) kopiert es zurück. Die Adresse wird als offset(register) geschrieben.

Der RISC-V-Speicher ist byte-adressiert, also hat jedes Byte seine eigene Adresse in Folge. Ein Wort ist 32 Bits oder 4 Bytes, also erhöht man einen Speicherzeiger um 4, um das nächste Wort zu erreichen. Deshalb sind Array-Offsets 0, 4, 8 und so weiter. Auf echter Hardware kann das Laden eines Wortes von einer Adresse, die kein Vielfaches von 4 ist, langsam sein oder einen Trap auslösen. Dieser Simulator erlaubt es, aber Sie sollten sich angewöhnen, Wörter auf 4 Bytes ausgerichtet zu halten.

Form laden / speichern
lw t0, 0(a1) # t0 = Speicher an Adresse a1
sw t0, 4(a1) # Speicher an Adresse a1+4 = t0

In offset(register) wird die kleine Offset-Zahl zur Adresse im Register addiert. 0(a1) ist die Adresse in a1 selbst, und 4(a1) ist 4 Bytes dahinter. So erreichen Sie nahegelegene Werte, ohne das Basisregister zu ändern.

Speichern im Arbeitsspeicher
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

Register und Speicher beginnen bei null.

In der Animation bleibt das Basisregister a0 gleich. Nur der in der Anweisung geschriebene literale Offset erhöht sich und bewegt sich zur nächsten Zielspeicheradresse. Um Speicher zu erstellen, der diesem Muster entspricht, reservieren Sie benannten Speicher im Datensegment mit .word (ein oder mehrere 32-Bit-Werte) oder .space N (N leere Bytes). Jedes Wort belegt 4 Bytes, also liegen aufeinanderfolgende Elemente bei den Offsets 0, 4, 8, die dieselben Zahlen sind, die in Ihren Store-Anweisungen verwendet werden.

Verwenden Sie .word (ein oder mehrere 32-Bit-Werte) oder .space N (N leere Bytes), um benannten Speicher im Datensegment zu reservieren. Jedes Wort belegt 4 Bytes, also liegen aufeinanderfolgende Elemente bei den Offsets 0, 4, 8 und so weiter.

Ein Array im Speicher summieren
.data
nums: .word 10, 20, 30, 40 # vier Wörter
.text
la t1, nums # t1 = Adresse des Arrays
li t2, 4 # Zähler
li t0, 0 # laufende Summe
loop:
beq t2, zero, done
lw t3, 0(t1) # lädt das aktuelle Element
add t0, t0, t3 # zur Summe addieren
addi t1, t1, 4 # zum nächsten Wort weiter (4 Bytes)
addi t2, t2, -1 # eines weniger
j loop
done:
mv a0, t0 # gibt die Summe aus (100)
li a7, 1
ecall
li a7, 10
ecall

legt die Adresse des Arrays in t1, t2 zählt die 4 verbleibenden Elemente, und t0 hält die laufende Summe. Bei jedem Durchlauf stoppt die Schleife, wenn keine Elemente mehr übrig sind. lädt das Element, auf das t1 zeigt, addiert es zur Summe, erhöht den Zeiger um ein Wort, und verringert den Zähler. Nach allen vier Elementen (10 + 20 + 30 + 40) gibt done 100 aus.

💡
Verwenden Sie den HEX/DEC-Umschalter in der Symbolleiste des Simulators, um die Anzeige von Adressen und Werten umzustellen. Wählen Sie die Basis, die den aktuellen Schritt leichter nachvollziehbar macht.