Память: загрузка и сохранение
Память — это большой ряд пронумерованных ячеек хранения, и каждая ячейка содержит один байт (8 бит). Номер ячейки — это её адрес. Регистры — это небольшой набор быстрых ячеек процессора. Память гораздо больше, но медленнее, и хранит всё, что не помещается в регистрах, например массивы и строки. Чтобы работать со значением в памяти, вы загружаете его в регистр, изменяете и сохраняете обратно.
Регистров мало, а память велика. (load word) копирует слово из памяти в регистр, а (store word) копирует его обратно. Адрес записывается как offset(register).
Память RISC-V адресуется побайтово, поэтому каждый байт имеет свой собственный адрес в последовательности. Слово — это 32 бита, или 4 байта, поэтому вы продвигаете указатель памяти на 4, чтобы достичь следующего слова. Именно поэтому смещения массива равны 0, 4, 8 и так далее. На реальном оборудовании загрузка слова с адреса, не кратного 4, может быть медленной или вызвать ловушку. Этот симулятор это допускает, но вам следует выработать привычку выравнивать слова по 4 байтам.
lw t0, 0(a1) # t0 = память по адресу a1sw 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 (одно или несколько 32-битных значений) или .space N (N пустых байтов). Каждое слово занимает 4 байта, поэтому последовательные элементы располагаются по смещениям 0, 4, 8, которые совпадают с числами, используемыми в ваших инструкциях сохранения.Используйте .word (одно или несколько 32-битных значений) или .space N (N пустых байтов), чтобы зарезервировать именованную память в секции данных. Каждое слово занимает 4 байта, поэтому последовательные элементы находятся по смещениям 0, 4, 8 и так далее.
.datanums: .word 10, 20, 30, 40 # четыре слова.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 # на один меньшеj loopdone:mv a0, t0 # печатает итог (100)li a7, 1ecallli a7, 10ecall
помещает адрес массива в t1, t2 подсчитывает оставшиеся 4 элемента, а t0 хранит текущую сумму. На каждом проходе останавливает цикл, когда не остаётся элементов. загружает элемент, на который указывает t1, добавляет его к сумме, продвигает указатель на одно слово, а уменьшает счётчик. После всех четырёх элементов (10 + 20 + 30 + 40) done выводит 100.
