Memoria: cargar y almacenar

Memoria: cargar y almacenar

La memoria es una gran fila de ranuras de almacenamiento numeradas, y cada ranura contiene un byte (8 bits). El número de una ranura es su dirección. Los registros son el pequeño conjunto de ranuras rápidas de la CPU. La memoria es mucho más grande pero más lenta, y contiene todo lo que no cabe en los registros, como los arreglos y las cadenas. Para trabajar con un valor en memoria, lo cargas en un registro, lo modificas y lo vuelves a almacenar.

Los registros son pocos y la memoria es grande. (load word) copia una palabra desde la memoria a un registro, y (store word) la copia de vuelta. La dirección se escribe como offset(register).

La memoria de RISC-V está direccionada por bytes, por lo que cada byte tiene su propia dirección en secuencia. Una palabra es de 32 bits, o 4 bytes, así que avanzas un puntero de memoria en 4 para llegar a la siguiente palabra. Por eso los desplazamientos de los arreglos son 0, 4, 8, etc. En hardware real, cargar una palabra desde una dirección que no es múltiplo de 4 puede ser lento o puede provocar una trampa. Este simulador lo permite, pero deberías formar el hábito de mantener las palabras alineadas a 4 bytes.

Cargar / almacenar forma
lw t0, 0(a1) # t0 = memoria en la dirección a1
sw t0, 4(a1) # memoria en la dirección a1+4 = t0

En offset(register), el número de desplazamiento pequeño se suma a la dirección contenida en el registro. 0(a1) es la dirección en a1 mismo, y 4(a1) está 4 bytes más allá. Esto te permite alcanzar valores cercanos sin cambiar el registro base.

Almacenando en memoria
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

Los registros y la memoria comienzan en cero.

En la animación, el registro base a0 permanece igual. Solo aumenta el desplazamiento literal escrito en la instrucción, avanzando a la siguiente dirección de memoria objetivo. Para crear memoria que coincida con este patrón, reserva memoria con nombre en la sección de datos con .word (uno o más valores de 32 bits) o .space N (N bytes en blanco). Cada palabra ocupa 4 bytes, por lo que los elementos consecutivos se sitúan en los desplazamientos 0, 4, 8, que son los mismos números usados en tus instrucciones de almacenamiento.

Usa .word (uno o más valores de 32 bits) o .space N (N bytes en blanco) para reservar memoria con nombre en la sección de datos. Cada palabra ocupa 4 bytes, por lo que los elementos consecutivos están en los desplazamientos 0, 4, 8, etc.

Suma un array en memoria
.data
nums: .word 10, 20, 30, 40 # cuatro palabras
.text
la t1, nums # t1 = dirección del arreglo
li t2, 4 # contador
li t0, 0 # suma acumulada
loop:
beq t2, zero, done
lw t3, 0(t1) # carga el elemento actual
add t0, t0, t3 # suma al total
addi t1, t1, 4 # avanza a la siguiente palabra (4 bytes)
addi t2, t2, -1 # uno menos
j loop
done:
mv a0, t0 # imprime el total (100)
li a7, 1
ecall
li a7, 10
ecall

pone la dirección del arreglo en t1, t2 cuenta los 4 elementos restantes, y t0 contiene la suma acumulada. En cada pasada, detiene el bucle cuando no quedan elementos. carga el elemento al que apunta t1, lo suma a la suma, avanza el puntero una palabra, y reduce el contador. Tras los cuatro elementos (10 + 20 + 30 + 40), done imprime 100.

💡
Usa el conmutador HEX/DEC en la barra de herramientas del simulador para cambiar cómo se muestran las direcciones y los valores. Elige la base que haga que el paso actual sea más fácil de seguir.