Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Die Befehle eines Prozessors lesen (RISC-V)

Nach dieser Lektion: Ich kann ein kurzes RISC-V-Programm lesen.

Lektion, 55 Min.10 BefehleLab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Ein Absturzbericht mit einer Zeile

Das Kartenterminal einer Bäckerei stürzt mitten am Morgen ab. Der Bericht, den es an den Hersteller schickt, nennt nur den letzten Befehl: sw a1, 12(sp).

Auf dem Terminal gibt es keinen Quelltext, nur Maschinenbefehle. Wer sie lesen kann, sieht, was das Programm beim Absturz gerade tat.

Am Ende dieser Lektion

Notiz

Ich kann ein kurzes RISC-V-Programm lesen.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Registerein kleiner, schneller Speicher im Prozessora0
Direktwerteine Zahl, die im Befehl selbst steht93
Ladenein Befehl, der einen Wert aus dem Speicher in ein Register kopiertlw
Speichernein Befehl, der ein Register in den Speicher kopiertsw
Verzweigungein Befehl, der an eine andere Stelle im Programm springen kannbne
Markeein Name für eine Stelle im Programmloop:

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Zweiunddreißig Register mit Aufgaben

Ein 64-Bit-Prozessor mit RISC-V hat 32 Register zu je 64 Bits, x0 bis x31. Im Assembler haben die meisten einen Namen für ihre übliche Aufgabe.

x0 heißt zero: Es liest sich immer als 0, und was man hineinschreibt, geht verloren. Die a-Register tragen die Eingaben einer Funktion und ihr Ergebnis. Die t-Register halten kurzlebige Zwischenwerte.

Beispiel: Register, die Ihnen begegnen

NummerNameÜbliche Aufgabe
x0zeroImmer 0
x2spDer Stack-Zeiger: wo der Stapel im Speicher liegt
x5 bis x7t0 bis t2Zwischenwerte
x10, x11a0, a1Eingaben einer Funktion, das Ergebnis in a0
x17a7Welchen Systemaufruf ecall von Linux verlangt

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

In den Architektur-Ordner wechseln

Befehl
cd ~/arch

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Drei Formen von Befehlen

Die meisten Befehle nennen zuerst das Zielregister und dann, woher die Eingaben kommen.

add a0, a0, t0 addiert zwei Register. addi t0, t0, 2 addiert ein Register und einen Direktwert, eine Zahl im Befehl. li a0, 5 sieht aus wie eine dritte Art, ist aber eine Abkürzung. Für eine kleine Zahl schreibt der Assembler addi a0, zero, 5.

Laden und Speichern erreichen den Speicher

Register sind wenige, also liegen Daten im Speicher. RISC-V rechnet nur mit Registern. Ein Ladebefehl kopiert aus dem Speicher in ein Register, ein Speicherbefehl in die andere Richtung.

lw a0, 8(a1) lädt ein Wort von 4 Bytes von der Adresse in a1 plus 8. Ein int in C hat 4 Bytes. Das loop.c des Labs füllt eine Tabelle und summiert sie, also muss gcc laden und speichern.

loop.c in RISC-V-Assembler übersetzen

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

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die Lade- und Speicherbefehle finden

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

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die Schleife Zeile für Zeile

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

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Beispiel: C neben RISC-V

C in loop.cRISC-VWas es tut
grid[r][c] = 1;sw a3,0(a5)Schreibt a3, das 1 enthält, an die Adresse in a5
sum = sum + grid[r][c];lw a4,0(a5)Liest 4 Bytes von der Adresse in a5 nach a4
sum = sum + grid[r][c];add a3,a3,a4Zählt die Zahl zur Summe dazu, in Registern
das nächste caddi a5,a5,4Rückt die Adresse um ein int weiter, 4 Bytes

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein häufiger Fehler

Warnung

Viele glauben, add könne eine Zahl direkt aus dem Speicher addieren. Bei RISC-V geht das nicht. Nur Lade- und Speicherbefehle berühren den Speicher. Ein Wert wird geladen, in Registern verarbeitet und zurückgespeichert. Deshalb braucht die Summe erst lw und dann add.

Eine Verzweigung baut eine Schleife

Eine Verzweigung vergleicht zwei Register und springt, wenn der Test stimmt. beq springt bei Gleichheit, bne bei Ungleichheit.

Eine Marke wie loop: benennt das Sprungziel. Das nächste Programm addiert die geraden Zahlen von 2 bis 20. t0 zählt in Zweierschritten, a0 hält die Summe, und bne t0, t1, loop springt zurück, bis t0 den Wert 22 erreicht.

Eine Schleife in RISC-V schreiben

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

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Assemblieren

Befehl
riscv64-linux-gnu-as gerade.s -o gerade.o

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Linken

Befehl
riscv64-linux-gnu-ld gerade.o -o gerade

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Im Emulator ausführen

Befehl
qemu-riscv64 ./gerade

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die Summe lesen

Befehl
echo $?

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ohne Abkürzungen zurücklesen

Befehl
riscv64-linux-gnu-objdump -d -M no-aliases gerade

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Weiterführend: multiplizieren ohne mul

Schreiben Sie ein RISC-V-Programm, das 8 mal 9 nur mit li, add, addi und einer Verzweigung rechnet: neunmal 8 zur Summe addieren.

Führen Sie es zuerst in Ihrem Interpreter aus. Schreiben Sie es dann wie gerade.s mit printf in eine Datei, bauen Sie es und führen Sie es im Lab aus. Der Exit-Status sollte 72 sein.

Über dieses Lab und seinen Quellcode: Lab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.