- Tutorial interactivo para aprender ensamblador RISC-V paso a paso mediante un emulador ejecutable en el navegador web, creado con inspiración en Easy 6502 de Nick Morgan
- Cubre las 45 instrucciones base del conjunto RV32I_Zicsr y los conceptos clave de la arquitectura con privilegios, enseñando un conjunto de instrucciones lo bastante completo como objetivo de compilador
- Ofrece fundamentos de la programación en ensamblador con ejemplos prácticos, incluyendo operaciones aritméticas/lógicas, bifurcaciones/saltos, acceso a memoria, convención de llamadas a funciones y manejo de pila
- Explica con código real la transición entre niveles de privilegio entre modo Machine y modo User, el manejo de excepciones y la manipulación de CSR (registros de control y estado)
- El objetivo final del tutorial es escribir directamente un sistema operativo diminuto con soporte para llamadas al sistema y manejo de excepciones, permitiendo experimentar el flujo completo del desarrollo de bajo nivel en RISC-V
Estructura del tutorial y principales contenidos de aprendizaje
Instrucciones básicas y conceptos del procesador
- Estado del procesador: comprensión del contador de programa (
pc), 31 registros de propósito general (x1~x31) y el registro cero especial (x0)
- Instrucciones aritméticas: aprendizaje de suma/resta y del comportamiento del overflow mediante
add, addi, sub, etc.
- Operaciones de bits: práctica con operaciones lógicas a nivel de bit e instrucciones de desplazamiento como
and, or, xor, sll, srl, sra
- Instrucciones de comparación: implementación de lógica de comparación y evaluación condicional para enteros con y sin signo usando
slt, sltu, etc.
Flujo de control y memoria
- Bifurcaciones y saltos: mecanismos de bifurcación condicional/incondicional y llamadas a funciones usando
beq, bne, blt, jal, jalr, etc.
- Acceso a memoria: operaciones de carga/almacenamiento por palabra, media palabra y byte mediante las instrucciones
lw, sw, lb, lh, sb, sh
- I/O mapeada en memoria: comprensión de cómo comunicarse con dispositivos externos mediante lectura/escritura sobre direcciones específicas
- Código independiente de la posición: técnicas para escribir código reubicable mediante la instrucción
auipc y direccionamiento relativo al PC
Funciones y convención de llamadas
- Alias de registros: roles de
a0~a7 (argumentos), s0~s11 (preservados), t0~t6 (temporales), ra (dirección de retorno), sp (puntero de pila), etc.
- Manejo de pila: patrones para guardar registros al entrar a una función, asignar/liberar espacio en la pila y preservar/restaurar la dirección de retorno
- Funciones recursivas: práctica de llamadas recursivas y manejo de marcos de pila mediante la implementación de la secuencia de Fibonacci
Arquitectura con privilegios y sistema operativo
- Niveles de privilegio: diferencias entre modo Machine (nivel 3) y modo User (nivel 0), y mecanismos de aislamiento
- Instrucciones CSR: lectura/escritura de registros de control y manipulación de campos de bits con
csrrw, csrrs, csrrc, etc.
- Manejo de excepciones: verificación de información de excepciones y escritura de handlers usando los CSR
mcause, mepc, mtval, mstatus
- Cambio de modo: entrada y retorno al modo User con la instrucción
mret, y cambio de contexto con mscratch
Proyecto final: OS diminuto
- Implementación de llamadas al sistema: uso de la instrucción
ecall para hacer trap desde modo User a modo Machine y ofrecer funciones putchar/exit
- Guardado/restauración de registros: estructura completa del trap handler que respalda y restaura todos los registros de propósito general en la pila
- Lógica de manejo de excepciones: identificación de la causa con
mcause, despacho según el número de llamada al sistema (a7) e impresión de mensajes de error
- Código ejecutable: se ofrece código completo de entrada/retorno del kernel del OS que puede ejecutarse directamente en el emulador web
Material de referencia y licencia
- Tanto el tutorial como el código están bajo dominio público CC0 o licencia BSD de 0 cláusulas
- Texto original y repositorio de código: https://github.com/dramforever/easyriscv
- Adecuado para aprendizaje de RISC-V, educación, investigación y construcción de entornos de simulación
2 comentarios
Guau
Como me empezó a interesar el ensamblador RISC-V que vemos en las materias de la carrera... incluso cuando pensaba en comprar un libro por mi cuenta solo encontraba sobre arquitectura ARM y nada de RISC-V, así que estaba dándole vueltas a qué debería ver, y justo parece que encontré un recurso excelente para estudiar
¡¡¡Gracias!!!
Opiniones de Hacker News
Fue una guía realmente muy buena
Me habría gustado que la pantalla del emulador de “My first RISC-V assembly program” apareciera al principio de la guía. Si no, los lectores podrían pensar que es solo una introducción con texto a pesar del título “interactive”
Planeo dedicarle más tiempo en los próximos días. Me interesa bastante RISC-V y creo que tiene un futuro brillante
Si algún experto en IA ve esto, estaría increíble que recreara Core War en ensamblador RISC-V con una plataforma como Replit o Lovable
Aprendí ensamblador con Computer Organization And Design de Patterson y Hennessy, y se nota claramente cuánto tomó RISC-V de MIPS
En ambas ISA participaron las mismas personas, y evitaron errores de MIPS como el delay slot. Si tienes experiencia con MIPS, el ensamblador de RISC-V se siente casi igual
Últimamente también he estado viendo AArch64, y aunque es menos limpio que RISC-V, su diseño práctico me parece impresionante. Incluso me hace pensar si RISC-V no fue diseñado de forma demasiado conservadora
Yo mismo escribí TCP Socket in RISC-V Assembly
Usé la ISA RV64I, y hay que entender el concepto de linker relaxation. También dejé material de referencia
Creo que hay un error en la sección de Position Independence
Me pregunto si para que salga 0x3004 no habría que usar
luien lugar deauipcen el código de ejemploluigenera una dirección absoluta, mientras que la combinaciónauipc/addicrea una dirección independiente de la posición. Siauipcestuviera en la dirección 0, el resultado sería el mismo, pero en la práctica se suma a la dirección de la instrucción actualLa estructura interactiva de este contenido es realmente excelente
Como desarrollador de C/C++, siempre pensé que el ensamblador era difícil, pero con este enfoque se entiende mucho más claro
load4en lugar delw, ojumpen vez dej; no estamos en la era de las tarjetas perforadas, así que no entiendo por qué todo tiene que ser tan cortoEste artículo me dio ganas de volver a hacer programación de bajo nivel
Estudié mecatrónica en la universidad y trabajé con microcontroladores en C y ensamblador, pero ahora me cambié al desarrollo web
Me pregunto si hay algún recurso confiable para aprender hardware RISC-V. Si es posible, me gustaría hacerlo con Rust
También había un tutorial de SO basado en Rust, pero ahora no encuentro el enlace
Si quieres hardware real, recomiendo neorv32 — tiene buena documentación: documentación oficial, repositorio en GitHub. Es un núcleo RISC-V escrito en VHDL
Es fácil conseguir hardware RISC-V
Mira RISC-V on Raspberry Pi Pico 2
Mira la página de Kickstarter
Y si quieres trabajar con RISC-V y FPGA al mismo tiempo, también está PolarFireSoC. Es mucho más barato y bastante usable comparado con AMD/Xilinx. El entorno de desarrollo es algo viejo pero rápido, la documentación está dispersa, pero casi todo existe en algún lado
Enlace al kit de desarrollo
Lo curioso es que la placa de desarrollo cuesta menos que el chip
Justo esta semana entramos a la unidad de introducción al ensamblador en una clase de C, y pensé que aprenderlo con RISC-V podría evitar el problema de las diferencias entre CPU
Pero resulta que alguien ya hizo un material que lo organiza perfectamente. Muchas gracias
En el ejemplo de “si restas desde 0 obtienes un número negativo”, el negativo de 0x123 es 0xfffffedd
Decían que el emulador mostraba 0xfffffccd, pero en realidad 0xfffffedd es lo correcto. Lo calculé yo mismo y el emulador está bien
Si buscas un buen emulador de RISC-V, recomiendo RARS