Easy RISC-V : tutoriel interactif d’introduction à la programmation en assembleur RISC-V
(dramforever.github.io)- Un tutoriel interactif permettant d’apprendre pas à pas l’assembleur RISC-V via un émulateur exécutable dans le navigateur web, inspiré de Easy 6502 de Nick Morgan
- Couvre les 45 instructions de base de l’ensemble d’instructions RV32I_Zicsr ainsi que les concepts essentiels de l’architecture privilégiée, avec un jeu d’instructions suffisamment complet pour servir de cible de compilation
- Propose les bases de la programmation en assembleur avec des exemples pratiques : opérations arithmétiques/logiques, branchements/sauts, accès mémoire, convention d’appel des fonctions, gestion de la pile, etc.
- Explique à l’aide de code concret la transition entre niveaux de privilège entre le mode Machine et le mode User, le traitement des exceptions et la manipulation des CSR (registres de contrôle et d’état)
- L’objectif final du tutoriel est d’écrire soi-même un micro-système d’exploitation prenant en charge les appels système et le traitement des exceptions, afin d’expérimenter l’ensemble du flux du développement bas niveau sur RISC-V
Structure du tutoriel et principaux contenus d’apprentissage
Instructions de base et concepts du processeur
- État du processeur : compréhension du compteur ordinal (pc), des 31 registres généraux (x1~x31) et du registre zéro spécial (x0)
- Instructions arithmétiques : apprentissage de l’addition/soustraction et du comportement en cas de dépassement avec
add,addi,sub, etc. - Opérations sur les bits : pratique des opérations logiques bit à bit et des décalages avec
and,or,xor,sll,srl,sra, etc. - Instructions de comparaison : implémentation de comparaisons d’entiers signés/non signés et de logique conditionnelle avec
slt,sltu, etc.
Flux de contrôle et mémoire
- Branchements et sauts : mécanismes de branchement conditionnel/inconditionnel et d’appel de fonction avec
beq,bne,blt,jal,jalr, etc. - Accès mémoire : opérations de chargement/stockage au niveau mot, demi-mot et octet avec les instructions
lw,sw,lb,lh,sb,sh - I/O mappées en mémoire : compréhension de la communication avec des périphériques externes via des lectures/écritures à des adresses spécifiques
- Code indépendant de la position : techniques d’écriture de code relogeable avec l’instruction
auipcet l’adressage relatif au PC
Fonctions et convention d’appel
- Alias de registres : rôles de
a0~a7(arguments),s0~s11(préservés),t0~t6(temporaires),ra(adresse de retour),sp(pointeur de pile), etc. - Gestion de la pile : schémas de sauvegarde des registres à l’entrée d’une fonction, allocation/libération de l’espace pile, préservation et restauration de l’adresse de retour
- Fonctions récursives : pratique des appels récursifs et de la gestion des stack frames via l’implémentation de la suite de Fibonacci
Architecture privilégiée et système d’exploitation
- Niveaux de privilège : différences entre le mode Machine (niveau 3) et le mode User (niveau 0), ainsi que les mécanismes d’isolation
- Instructions CSR : lecture/écriture des registres de contrôle et manipulation de champs de bits avec
csrrw,csrrs,csrrc, etc. - Traitement des exceptions : vérification des informations d’exception et écriture de gestionnaires à l’aide des CSR
mcause,mepc,mtval,mstatus - Changement de mode : entrée en mode User et retour avec l’instruction
mret, et bascule de contexte à l’aide demscratch
Projet final : micro-OS
- Implémentation des appels système : utilisation de l’instruction
ecallpour trapper du mode User vers le mode Machine et fournir les fonctions putchar/exit - Sauvegarde/restauration des registres : structure complète d’un gestionnaire de trap qui sauvegarde et restaure tous les registres généraux sur la pile
- Logique de traitement des exceptions : identification de la cause via
mcause, dispatch selon le numéro d’appel système (a7) et affichage des messages d’erreur - Code exécutable : fourniture d’un code complet d’entrée/sortie du noyau OS directement exécutable dans l’émulateur web
Ressources complémentaires et licence
- Le tutoriel comme le code sont placés sous domaine public CC0 ou sous licence BSD à 0 clause
- Texte original et dépôt de code : https://github.com/dramforever/easyriscv
- Adapté à l’apprentissage de RISC-V ainsi qu’à la mise en place d’environnements d’enseignement, de recherche et de simulation
2 commentaires
Waouh
Je me suis intéressé à l’assembleur RISC-V qu’on apprend dans les cours de spécialité… Même en voulant acheter un livre à part, je ne voyais que des ouvrages sur l’architecture ARM et rien sur RISC-V, donc je me demandais quoi consulter. Et là, j’ai l’impression d’avoir trouvé une ressource vraiment idéale pour étudier.
Merci beaucoup !!!
Avis Hacker News
C’était vraiment un excellent guide
J’aurais aimé que le premier écran de l’émulateur « My first RISC-V assembly program » soit placé tout au début du guide. Sinon, les lecteurs pourraient croire qu’il s’agit simplement d’une introduction textuelle malgré le terme « interactive » dans le titre
Je vais probablement y consacrer encore quelques jours. Je m’intéresse beaucoup à RISC-V et je pense qu’il a un bel avenir
Si un spécialiste IA lit ceci, ce serait vraiment génial que quelqu’un recrée Core War en assembleur RISC-V avec une plateforme comme Replit ou Lovable
J’ai appris l’assembleur avec Computer Organization And Design de Patterson et Hennessy, et on sent clairement à quel point RISC-V a repris de choses à MIPS
Les mêmes personnes ont participé aux deux ISA, et ils ont évité des erreurs comme le delay slot de MIPS. Si vous avez déjà de l’expérience avec MIPS, l’assembleur RISC-V paraîtra presque identique
En ce moment, je regarde aussi AArch64, et même si c’est moins élégant que RISC-V, sa conception pragmatique est impressionnante. J’en viens même à me demander si RISC-V n’a pas été conçu de manière un peu trop conservatrice
J’ai moi-même écrit TCP Socket in RISC-V Assembly
J’ai utilisé l’ISA RV64I, et il faut comprendre le concept de linker relaxation. J’ai aussi joint des ressources de référence
Je pense qu’il y a une erreur dans la section sur l’indépendance de position
Dans l’exemple de code, ne faudrait-il pas utiliser
luiau lieu deauipcpour obtenir 0x3004 ?luigénère une adresse absolue, tandis que la combinaisonauipc/addiproduit une adresse indépendante de la position. Siauipcse trouvait à l’adresse 0, le résultat serait identique, mais en pratique la valeur est ajoutée à l’adresse de l’instruction couranteLa construction interactive de ce contenu est vraiment excellente
En tant que développeur C/C++, j’ai toujours trouvé l’assembleur difficile, mais avec cette approche, c’est bien plus clair
load4au lieu delw, oujumpau lieu dej. On n’est plus à l’époque des cartes perforées, alors je ne vois pas pourquoi tout est si courtCet article m’a donné envie de refaire un peu de programmation bas niveau
J’ai étudié la mécatronique à l’université et travaillé sur des microcontrôleurs en C et en assembleur, mais aujourd’hui je suis passé au développement web
Je me demande s’il existe des ressources fiables pour apprendre le matériel RISC-V. Si possible, j’aimerais le faire avec Rust
Il y avait aussi un tutoriel d’OS en Rust, mais je n’arrive plus à retrouver le lien
Si vous voulez du vrai matériel, je recommande neorv32 — la documentation est solide : documentation officielle, dépôt GitHub. C’est un cœur RISC-V écrit en VHDL
Le matériel RISC-V se trouve facilement
Voir RISC-V on Raspberry Pi Pico 2
Voir la page Kickstarter
Et si vous voulez travailler à la fois avec RISC-V et des FPGA, il y a aussi PolarFireSoC. C’est bien moins cher que chez AMD/Xilinx et tout à fait utilisable. L’environnement de développement est un peu vieille école mais rapide, la documentation est éparpillée mais la plupart des infos existent quelque part
Lien vers le kit de développement
Le point amusant, c’est que la carte de développement coûte moins cher que la puce elle-même
Justement cette semaine, dans un cours de C, on est entrés dans le chapitre d’introduction à l’assembleur, et je me disais qu’apprendre avec RISC-V permettrait d’éviter les problèmes liés aux différences entre CPU
Mais quelqu’un avait déjà préparé exactement la ressource qu’il fallait. Un grand merci
Dans l’exemple « soustraire à partir de 0 donne un nombre négatif », l’opposé de 0x123 est 0xfffffedd
Il était dit que l’émulateur affichait 0xfffffccd, mais en réalité 0xfffffedd est correct. J’ai refait le calcul moi-même et l’émulateur a raison
Si vous cherchez un bon émulateur RISC-V, je recommande RARS