Память: загрузка и сохранение

Память: загрузка и сохранение

Память — это большой ряд пронумерованных ячеек хранения, и каждая ячейка содержит один байт (8 бит). Номер ячейки — это её адрес. Регистры — это небольшой набор быстрых ячеек процессора. Память гораздо больше, но медленнее, и хранит всё, что не помещается в регистрах, например массивы и строки. Чтобы работать со значением в памяти, вы загружаете его в регистр, изменяете и сохраняете обратно.

Регистров мало, а память велика. (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 (одно или несколько 32-битных значений) или .space N (N пустых байтов). Каждое слово занимает 4 байта, поэтому последовательные элементы располагаются по смещениям 0, 4, 8, которые совпадают с числами, используемыми в ваших инструкциях сохранения.

Используйте .word (одно или несколько 32-битных значений) или .space N (N пустых байтов), чтобы зарезервировать именованную память в секции данных. Каждое слово занимает 4 байта, поэтому последовательные элементы находятся по смещениям 0, 4, 8 и так далее.

Суммирование массива в памяти
.data
nums: .word 10, 20, 30, 40 # четыре слова
.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 # на один меньше
j loop
done:
mv a0, t0 # печатает итог (100)
li a7, 1
ecall
li a7, 10
ecall

помещает адрес массива в t1, t2 подсчитывает оставшиеся 4 элемента, а t0 хранит текущую сумму. На каждом проходе останавливает цикл, когда не остаётся элементов. загружает элемент, на который указывает t1, добавляет его к сумме, продвигает указатель на одно слово, а уменьшает счётчик. После всех четырёх элементов (10 + 20 + 30 + 40) done выводит 100.

💡
Используйте переключатель HEX/DEC на панели инструментов симулятора, чтобы изменить отображение адресов и значений. Выберите ту систему счисления, которая упрощает отслеживание текущего шага.