¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Leer las instrucciones del procesador (RISC-V)

Después de esta lección: Puedo leer un programa corto en RISC-V.

Lección de 55 min10 comandosLaboratorio de compiladores y arquitectura: gcc, flex, bison y RISC-V en una VM

El informe con una sola línea

El terminal de cobro de una cadena de tiendas se bloquea en mitad de una venta. El informe de fallo solo trae la última instrucción que ejecutó: sw a1, 0(a0).

En el terminal no hay código fuente, solo instrucciones. Quien sabe leerlas puede decir qué hacía el programa cuando se paró.

Al final de esta lección

Nota

Puedo leer un programa corto en RISC-V.

Palabras clave

PalabraQué significaEjemplo
Registroun almacén pequeño y rápido dentro del procesadora0
Inmediatoun número escrito dentro de la propia instrucción93
Cargauna instrucción que copia un valor de la memoria a un registrolw
Almacenamientouna instrucción que copia un registro en la memoriasw
Salto condicionaluna instrucción que puede saltar a otro punto del programabne
Etiquetaun nombre para un punto del programaloop:

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Treinta y dos registros con su tarea

Un procesador RISC-V de 64 bits tiene 32 registros de 64 bits, llamados de x0 a x31. En ensamblador, casi todos tienen además un nombre según su tarea habitual.

x0 se llama zero: siempre vale 0, y lo que se escribe en él se pierde. Los registros a llevan las entradas de una función y su resultado. Los registros t guardan valores de trabajo que duran poco.

Ejemplo resuelto: los registros que verás

NúmeroNombreTarea habitual
x0zeroSiempre vale 0
x2spEl puntero de pila: dónde está la pila en memoria
x5 a x7t0 a t2Valores de trabajo
x10, x11a0, a1Entradas de una función, y su resultado en a0
x17a7Qué llamada al sistema pide ecall a Linux

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Entra en la carpeta de arquitectura

Comando
cd ~/arch

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Tres formas de instrucción

Casi todas las instrucciones nombran primero el registro de destino y después de dónde salen los datos.

add a0, a0, t0 suma dos registros. addi t0, t0, 2 suma un registro y un inmediato, un número escrito dentro de la instrucción. li a0, 5 parece de otro tipo, pero es una abreviatura. Para un número pequeño, el ensamblador escribe addi a0, zero, 5.

Cargas y almacenamientos tocan la memoria

Hay pocos registros, así que los datos viven en la memoria. RISC-V solo calcula con registros. Una carga copia de la memoria a un registro, y un almacenamiento copia en sentido contrario.

lw a0, 8(a1) carga una palabra de 4 bytes desde la dirección de a1 más 8. Un int de C ocupa 4 bytes. El loop.c del laboratorio rellena una tabla y la suma, así que gcc tiene que cargar y almacenar.

Compila loop.c a ensamblador RISC-V

Comando
riscv64-linux-gnu-gcc -O2 -march=rv64gc -S loop.c

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Busca las cargas y el almacenamiento

Comando
grep -E 'lw|sw' loop.s

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Enseña el bucle por filas

Comando
grep -A 4 'L6:' loop.s

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejemplo resuelto: C junto a RISC-V

C en loop.cRISC-VQué hace
grid[r][c] = 1;sw a3,0(a5)Escribe a3, que vale 1, en la dirección de a5
sum = sum + grid[r][c];lw a4,0(a5)Lee 4 bytes de la dirección de a5 y los deja en a4
sum = sum + grid[r][c];add a3,a3,a4Suma el número al total, en registros
la siguiente caddi a5,a5,4Avanza la dirección un int, 4 bytes

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un error frecuente

Advertencia

Mucha gente cree que add puede sumar un número que está en la memoria. En RISC-V no puede. Solo las cargas y los almacenamientos tocan la memoria. Un valor se carga, se trabaja en registros y se vuelve a guardar. Por eso la suma necesita primero lw y después add.

Un salto condicional crea un bucle

Un salto condicional compara dos registros y salta si se cumple la prueba. beq salta cuando son iguales y bne cuando son distintos.

Una etiqueta como loop: nombra el punto al que se salta. El programa siguiente suma los pares de 2 a 12. t0 empieza en 2 y sube de dos en dos, a0 guarda el total, y bne t0, t1, loop vuelve atrás hasta que t0 llega a 14.

Escribe un bucle en RISC-V

Comando
printf '.globl _start\n_start:\n  li a0, 0\n  li t0, 2\n  li t1, 14\nloop:\n  add a0, a0, t0\n  addi t0, t0, 2\n  bne t0, t1, loop\n  li a7, 93\n  ecall\n' > pares.s

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ensámblalo

Comando
riscv64-linux-gnu-as pares.s -o pares.o

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Enlázalo

Comando
riscv64-linux-gnu-ld pares.o -o pares

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo en el emulador

Comando
qemu-riscv64 ./pares

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lee el total

Comando
echo $?

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Léelo de nuevo sin abreviaturas

Comando
riscv64-linux-gnu-objdump -d -M no-aliases pares

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Para ir más lejos: multiplicar sin mul

Escribe un programa RISC-V que calcule 8 por 5 usando solo li, add, addi y un salto condicional: suma 8 al total cinco veces.

Pruébalo primero en tu intérprete. Después escríbelo en un archivo con printf, como hiciste con pares.s, constrúyelo y ejecútalo en el laboratorio. El estado de salida debe ser 40.

Sobre este laboratorio y su código: Laboratorio de compiladores y arquitectura: gcc, flex, bison y RISC-V en una VM

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.