23 Punkte von GN⁺ 2025-10-28 | 2 Kommentare | Auf WhatsApp teilen
  • Ein interaktives Tutorial, mit dem man RISC-V-Assembly Schritt für Schritt über einen im Webbrowser lauffähigen Emulator lernen kann; inspiriert von Nick Morgans Easy 6502
  • Behandelt die 45 Basisbefehle des RV32I_Zicsr-Befehlssatzes sowie die Kernkonzepte der privilegierten Architektur und vermittelt einen für Compiler-Ziele hinreichend vollständigen Befehlssatz
  • Bietet Grundlagen der Assembly-Programmierung wie Arithmetik-/Logikoperationen, Verzweigungen/Sprünge, Speicherzugriffe, Funktionsaufrufkonventionen und Stack-Verwaltung zusammen mit Praxisbeispielen
  • Erklärt mit realem Code den Wechsel zwischen Privilegstufen zwischen Machine Mode und User Mode, die Ausnahmebehandlung sowie die Manipulation von CSRs (Control and Status Registers)
  • Das Endziel des Tutorials ist das eigenständige Schreiben eines winzigen Betriebssystems mit Unterstützung für System Calls und Ausnahmebehandlung, sodass sich der gesamte Ablauf der Low-Level-Entwicklung mit RISC-V nachvollziehen lässt

Aufbau des Tutorials und wichtigste Lerninhalte

Grundlegende Befehle und Prozessorkonzepte

  • Prozessorzustand: Verständnis von Program Counter (pc), 31 allgemeinen Registern (x1~x31) und dem speziellen Zero-Register (x0)
  • Arithmetische Befehle: Lernen von Addition/Subtraktion und dem Verhalten bei Overflow mit add, addi, sub usw.
  • Bitoperationen: Übungen zu logischen Bitoperationen und Shift-Befehlen wie and, or, xor, sll, srl, sra
  • Vergleichsbefehle: Umsetzung von Logik für vorzeichenbehaftete/vorzeichenlose Ganzzahlvergleiche und Bedingungen mit slt, sltu usw.

Kontrollfluss und Speicher

  • Verzweigungen und Sprünge: Mechanismen für bedingte/unbedingte Verzweigungen und Funktionsaufrufe mit beq, bne, blt, jal, jalr usw.
  • Speicherzugriff: Load-/Store-Operationen für Word, Halfword und Byte mit lw, sw, lb, lh, sb, sh
  • Memory-Mapped I/O: Verständnis dafür, wie über Lese-/Schreibzugriffe auf bestimmte Adressen mit externen Geräten kommuniziert wird
  • Positionsunabhängiger Code: Techniken zum Schreiben von relocatablem Code mit dem auipc-Befehl und PC-relativer Adressierung

Funktionen und Aufrufkonventionen

  • Register-Aliasse: Rollen von a0~a7 (Argumente), s0~s11 (gesichert), t0~t6 (temporär), ra (Rücksprungadresse), sp (Stack Pointer) usw.
  • Stack-Verwaltung: Muster zum Sichern von Registern beim Funktionseintritt, Reservieren/Freigeben von Stack-Speicher sowie zum Bewahren und Wiederherstellen der Rücksprungadresse
  • Rekursive Funktionen: Praxis mit rekursiven Aufrufen und Stack-Frame-Verwaltung anhand einer Fibonacci-Implementierung

Privilegierte Architektur und Betriebssystem

  • Privilegstufen: Unterschiede zwischen Machine Mode (Level 3) und User Mode (Level 0) sowie deren Isolationsmechanismen
  • CSR-Befehle: Lesen/Schreiben von Kontrollregistern und Manipulation von Bitfeldern mit csrrw, csrrs, csrrc usw.
  • Ausnahmebehandlung: Prüfen von Ausnahmeinformationen und Schreiben von Handlern mit den CSRs mcause, mepc, mtval, mstatus
  • Moduswechsel: Eintritt in den User Mode und Rückkehr mit dem mret-Befehl sowie Context Switching mit mscratch

Abschlussprojekt: winziges OS

  • Implementierung von System Calls: Trap von User Mode in Machine Mode mit dem ecall-Befehl, um putchar-/exit-Funktionen bereitzustellen
  • Sichern/Wiederherstellen von Registern: Vollständige Struktur eines Trap-Handlers, der alle allgemeinen Register auf dem Stack sichert und restauriert
  • Logik der Ausnahmebehandlung: Bestimmung der Ausnahmeursache mit mcause, Dispatch nach System-Call-Nummer (a7) und Ausgabe von Fehlermeldungen
  • Ausführbarer Code: Vollständiger Code für Einstieg und Rückkehr des OS-Kernels, direkt im Web-Emulator ausführbar

Referenzmaterialien und Lizenz

  • Tutorial und Code stehen vollständig unter CC0 Public Domain oder der 0-clause BSD-Lizenz
  • Original und Code-Repository: https://github.com/dramforever/easyriscv
  • Für das Lernen von RISC-V geeignet für Bildung, Forschung und den Aufbau von Simulationsumgebungen

2 Kommentare

 
lsdcnu 2025-11-06

Wow
Ich habe mich für RISC-V-Assembly interessiert, das man im Fachunterricht lernt ... Selbst wenn ich mir extra ein Buch kaufen und lesen wollte, habe ich nur ARM-Architektur gesehen und nichts zu RISC-V, also habe ich gerade überlegt, was ich mir ansehen sollte. Da scheint es, als hätte ich eine richtig gute Ressource zum Lernen gefunden.
Vielen Dank!!!

 
GN⁺ 2025-10-28
Hacker-News-Kommentare
  • Wirklich ein sehr guter Leitfaden.
    Ich wünschte, der Emulator-Bildschirm aus dem ersten „My first RISC-V assembly program“ stünde ganz am Anfang des Leitfadens. Sonst könnten Leser trotz des Titels „interactive“ denken, es handle sich nur um eine textbasierte Einführung.
    Ich werde mir in den nächsten Tagen noch mehr Zeit dafür nehmen. Ich interessiere mich ziemlich für RISC-V und denke, dass es eine vielversprechende Zukunft hat.
    Falls ein KI-Experte das hier liest: Es wäre wirklich großartig, wenn jemand Core War mit einer Plattform wie Replit oder Lovable noch einmal in RISC-V-Assembly umsetzen würde.

    • Warum nicht einfach direkt im Kopf machen?
  • Ich habe Assembly mit Patterson und Hennessys Computer Organization And Design gelernt, und man merkt deutlich, wie viel RISC-V von MIPS übernommen hat.
    An beiden ISAs waren dieselben Leute beteiligt, und man hat Fehler wie den delay slot von MIPS vermieden. Wenn man Erfahrung mit MIPS hat, fühlt sich RISC-V-Assembly fast genauso an.
    Ich schaue mir derzeit auch AArch64 an; es ist weniger elegant als RISC-V, aber das praktische Design ist beeindruckend. Manchmal frage ich mich sogar, ob RISC-V nicht zu konservativ entworfen wurde.

    • Vermutlich ist RISC-V näher an RISC-1. Patterson hat das selbst in diesen Artikeln erklärt: How close is RISC-V to RISC-I, RISC on a Chip
    • Ich hatte bei RISC-V und MIPS auch ein ähnliches Gefühl. Bei der Nintendo-64-Homebrew-Entwicklung dachte ich oft: „Das ist fast genau dasselbe wie das, womit ich früher in Ares+Godbolt herumgespielt habe, nur ohne delay slot.“
    • Vielen ist nicht bewusst, wie viele Unklarheiten es darüber gibt, woher das Design von AArch64 stammt und nach welcher Philosophie es entwickelt wurde.
    • Befehle lassen sich leicht hinzufügen, aber nur schwer wieder entfernen. RISC-V begann bewusst mit einem minimalen Befehlssatz und wird seitdem schrittweise erweitert. Wer neue Instruktionen vorschlägt, muss deren Kosten und praktischen Nutzen belegen.
    • Soweit ich mich erinnere, stand auch in Computer Architecture: A Quantitative Approach etwas über die Ähnlichkeit von RISC-V und MIPS. Das Buch liegt gerade in einer Kiste, daher kenne ich die genaue Seite nicht.
  • Ich habe selbst TCP Socket in RISC-V Assembly geschrieben.
    Dabei habe ich die RV64I-ISA verwendet, und man muss das Konzept der linker relaxation verstehen. Referenzmaterial habe ich ebenfalls beigefügt.

  • Im Abschnitt über Position Independence scheint es einen Fehler zu geben.
    Ich frage mich, ob im Beispielcode nicht lui statt auipc verwendet werden müsste, damit 0x3004 herauskommt.

    • Nein. lui erzeugt eine absolute Adresse, während die Kombination auipc/addi eine positionsunabhängige Adresse erzeugt. Wenn auipc an Adresse 0 steht, ist das Ergebnis identisch, tatsächlich wird aber ein Wert addiert, der von der Adresse der aktuellen Instruktion ausgeht.
  • Die interaktive Gestaltung dieses Inhalts ist wirklich hervorragend.
    Als C/C++-Entwickler fand ich Assembly immer schwierig, aber durch diese Herangehensweise ist es viel klarer geworden.

    • RISC-V-Assembly ist im Großen und Ganzen einfach, aber es gibt zu viele abgekürzte Instruktionsnamen, was ich unerquicklich finde. Statt lw könnte man load4 schreiben, statt j einfach jump — wir leben schließlich nicht mehr im Zeitalter der Lochkarten, also verstehe ich nicht, warum alles so kurz sein muss.
  • Dieser Artikel hat mir wieder Lust auf Low-Level-Programmierung gemacht.
    Ich habe im Studium der Mechatronik mit C und Assembly auf Mikrocontrollern gearbeitet, bin inzwischen aber in die Webentwicklung gewechselt.
    Mich würde interessieren, ob es vertrauenswürdige Ressourcen gibt, um RISC-V-Hardware zu lernen. Wenn möglich, würde ich das gern mit Rust machen.

    • Man arbeitet damit nicht direkt auf Hardwareebene in Rust, aber es gibt ein gutes Tutorial zu OS-Grundlagen: Operating System in 1000 Lines
      Außerdem gab es noch ein Rust-basiertes OS-Tutorial, aber den Link finde ich gerade nicht.
      Wenn du echte Hardware willst, empfehle ich neorv32 — die Dokumentation ist gut: offizielle Dokumentation, GitHub-Repository. Das ist ein in VHDL geschriebener RISC-V-Kern.
  • RISC-V-Hardware ist leicht zu bekommen.
    Siehe RISC-V on Raspberry Pi Pico 2.

    • Ich freue mich auch auf das bald erscheinende VisionFive 2 Lite. Bei Treibern und Leistung hat es zwar einige Schwächen, aber für OS-Entwicklung dürfte es in Ordnung sein.
      Siehe Kickstarter-Seite.
      Und wenn man RISC-V zusammen mit FPGA behandeln möchte, gibt es auch PolarFireSoC. Das ist deutlich günstiger als AMD/Xilinx und durchaus brauchbar. Die Entwicklungsumgebung ist etwas altmodisch, aber schnell, und die Dokumentation ist verstreut, aber das meiste findet sich irgendwo.
      Link zum Entwicklungskit
      Lustig ist, dass das Entwicklungsboard billiger ist als der Chip selbst.
    • Wahrscheinlich ist es einfacher, mit dem ESP-32 anzufangen. Der ist wesentlich leichter verfügbar.
  • Zufällig haben wir diese Woche in einer C-Vorlesung gerade mit dem Kapitel Einführung in Assembly begonnen, und ich dachte, mit RISC-V könnte man die Unterschiede zwischen CPUs elegant umgehen.
    Aber offenbar hat schon jemand genau dafür perfekt aufbereitetes Material erstellt. Vielen Dank dafür.

  • Im Beispiel „Wenn man von 0 subtrahiert, wird das Ergebnis negativ“ ist das Negative von 0x123 gleich 0xfffffedd.
    Es hieß, der Emulator zeige 0xfffffccd an, aber tatsächlich ist 0xfffffedd korrekt. Ich habe es selbst nachgerechnet, und der Emulator liegt richtig.

  • Wer einen guten RISC-V-Emulator sucht, dem empfehle ich RARS.