Gibt es eine Möglichkeit, gcc zu verwenden, um C in MIPS zu konvertieren?

Lesezeit: 12 Minuten

Benutzer-Avatar
Mike

Ich habe eine C-zu-MIPS-Konvertierung für eine Klasse abgeschlossen und möchte sie mit der Assembly vergleichen. Ich habe gehört, dass es eine Möglichkeit gibt, gcc so zu konfigurieren, dass es C-Code in die MIPS-Architektur und nicht in die x86-Architektur konvertieren kann (mein Computer verwendet einen Intel i5-Prozessor) und die Ausgabe druckt.

Welchen Befehl verwende ich, um das Terminal in Ubuntu (das mit gcc geliefert wird) auszuführen, um gcc für die Konvertierung in MIPS zu konfigurieren? Muss ich da auch was installieren?

EDIT: Lassen Sie mich klarstellen. Bitte lesen Sie dies. Ich suche nicht nach dem Compiler, den ich verwenden soll, oder nach Leuten, die sagen: “Nun, Sie könnten crosskompilieren, aber stattdessen sollten Sie dieses andere Ding verwenden, das keine Anweisungen zum Einrichten enthält.”

Wenn Sie das posten wollen, verweisen Sie mich zumindest auf Anweisungen. GCC kam mit Ubuntu. Ich habe keine Erfahrung mit der Installation von Compilern und es ist nicht einfach, Online-Tutorials für etwas anderes als GCC zu finden. Dann gibt es noch den Fall der Cross-Kompilierung, über den ich auch Bescheid wissen muss. Vielen Dank.

  • Sie möchten wahrscheinlich nur “kompilieren” und nicht “konvertieren”. Der Compiler “konvertiert” immer eine Sprache in eine andere. Wenn Sie auf x86-Boxen laufen, wird Ihre Quellsprache im Allgemeinen in eine x86-ausführbare Datei konvertiert, die für Ihr Betriebssystem geeignet ist, aber Compiler sind nicht darauf beschränkt, auf ihr Host-Betriebssystem und ihre Architektur abzuzielen …

    – dmckee — Ex-Moderator-Kätzchen

    14. November 2010 um 0:47 Uhr

  • Ja, das ist so etwas, was ich frage. Vielen Dank für die Korrektur meiner Terminologie, aber können Sie die eigentliche Frage beantworten?

    – Mike

    14. November 2010 um 1:05 Uhr

GCC kann Assembler-Code für eine große Anzahl von Architekturen produzieren, einschließlich MIPS. Auf welche Architektur eine bestimmte GCC-Instanz abzielt, wird jedoch entschieden, wenn GCC selbst kompiliert wird. Die vorkompilierte Binärdatei, die Sie in einem Ubuntu-System finden, kennt x86 (möglicherweise sowohl 32-Bit- als auch 64-Bit-Modus), aber nicht MIPS.

Das Kompilieren von GCC mit einer Zielarchitektur, die sich von der Architektur unterscheidet, auf der GCC selbst ausgeführt wird, wird als Vorbereitung einer Cross-Compilation-Toolchain. Das ist machbar, erfordert aber einiges an Dokumentationslektüre und Geduld; Normalerweise müssen Sie zuerst einen Cross-Assembler und Cross-Linker (GNU-Binutils) erstellen und dann den Cross-GCC selbst erstellen.

Ich empfehle die Verwendung buildroot. Dies ist eine Reihe von Skripten und Makefiles, die entwickelt wurden, um bei der Erstellung einer vollständigen Cross-Compilation-Toolchain und Dienstprogrammen zu helfen. Am Ende des Tages erhalten Sie ein komplettes Betriebssystem und Entwicklungstools für ein Zielsystem. Dies schließt den Cross-Compiler ein, nach dem Sie suchen.

Eine andere ganz andere Lösung ist zu verwenden QEMU. Dies ist ein Emulator für verschiedene Prozessoren und Systeme, einschließlich MIPS-Systemen. Sie können es verwenden, um eine virtuelle Maschine mit einem MIPS-Prozessor auszuführen und innerhalb dieser Maschine ein Betriebssystem für MIPS zu installieren, z Debian, eine Linux-Distribution. Auf diese Weise erhalten Sie eine einheimisch GCC (ein GCC, der auf einem MIPS-System läuft und Code für MIPS produziert).

Der QEMU-Weg könnte etwas einfacher sein; Die Verwendung von Cross-Compilation erfordert ein gewisses Verständnis einiger haariger Details. In jedem Fall benötigen Sie etwa 1 GB freien Speicherplatz.

  • Wenn ich könnte, Sir, würde ich Sie zweimal für diese Antwort positiv bewerten, Prost

    – timB33

    27. August 2011 um 21:18 Uhr

  • Wenn Sie nur den Cross-Compiler benötigen, installieren Sie ihn aus den Ubuntu-Repositories. Siehe: stackoverflow.com/a/58040917/5916915

    – Fluss

    22. September 2019 um 5:48 Uhr

Es ist keine Konfigurationssache, Sie benötigen eine Version von GCC, die zu MIPS kompiliert. Dies erfordert einen speziellen GCC-Build und ist ziemlich haarig einzurichten (das Bauen von GCC ist nichts für schwache Nerven).

Ich würde die Verwendung empfehlen LCC dafür. Es ist viel einfacher, mit LCC eine Kreuzkompilierung durchzuführen als mit GCC, und das Erstellen von LCC ist auf aktuellen Maschinen eine Sache von Sekunden.

  • Danke für die schnelle Antwort, aber sie umgeht meine Frage. Sie sagen mir ganz allgemein, was ich tun soll (Cross-Compiling?) Und leiten mich dann zu einem anderen Compiler weiter. Ich frage im Detail, wie ich diese Version von GCC bekomme und welche Befehle zu verwenden sind, nicht, ob ich GCC oder einen anderen Compiler verwenden sollte. Dann gibt es noch den Fall, diesen Compiler einzurichten, für den es auf der LCC-Site keinerlei Anweisungen gibt.

    – Mike

    14. November 2010 um 0:37 Uhr


  • Ich ging davon aus, dass Ihr Hauptinteresse darin bestand, C in die MIPS-Assembly zu kompilieren, nicht in GCC. Wenn Sie darauf bestehen, GCC dafür zu verwenden, machen Sie weiter, aber seien Sie gewarnt – es lohnt sich nicht, nur ein Programm zu kompilieren (insbesondere, wenn Sie Schwierigkeiten haben, LCC zum Erstellen zu bringen). Einige (relativ veraltete, aber ich habe nichts neueres gefunden) Anweisungen zum Erstellen von Cross-GCCs finden Sie hier: gcc.gnu.org/wiki/Building_Cross_Toolchains_with_gcc

    – Fabian Giesen

    14. November 2010 um 0:52 Uhr

  • Mein Fehler. Ich glaube ich habe deine Antwort falsch verstanden. Ja, mein Interesse besteht darin, C in MIPS umzuwandeln. Aber wenn Sie mir sagen, ich solle einen anderen Compiler verwenden, können Sie mich auf eine Stelle verweisen, die erklärt, wie man ihn einrichtet und dann mit ihm zu MIPS kreuzkompiliert? Beides kann ich nicht finden.

    – Mike

    14. November 2010 um 0:57 Uhr


  • Detaillierte Anweisungen zur Einrichtung finden Sie in der LCC-Distribution in doc/install.html. Was genau zu tun ist, hängt davon ab, auf welcher Hostplattform Sie kompilieren – Win32, Linux, etwas anderes? Um einen MIPS-Compiler zu erhalten, geben Sie in jedem Fall “mips/irix” als TARGET an, wenn Sie lcc erstellen.

    – Fabian Giesen

    14. November 2010 um 1:23 Uhr

Benutzer-Avatar
Peter Kordes

Für eine einmalige Verwendung für ein kleines Programm oder einige Funktionen müssen Sie nichts lokal installieren.

Verwenden Sie die Compiler-Explorer-Site von Matt Godbolt, https://godbolt.org/das GCC und Clang für verschiedene ISAs hat, darunter MIPS und x86-64, und einige andere Compiler.

Beachten Sie, dass der Compiler-Explorer standardmäßig Anweisungen filtert, damit Sie dies können nur siehe die Anweisungen, lassen Sie Dinge wie Ausrichtung, Abschnitte, .globl, usw. (Für eine Funktion ohne globale / statische Daten ist dies eigentlich in Ordnung, insbesondere wenn Sie nur einen Compiler verwenden möchten, um ein Beispiel für Sie zu erstellen. Der Standardabschnitt ist .text jedenfalls, wenn Sie keine Anweisungen verwenden.)


Die meisten Leute, die MIPS asm für Hausaufgaben wollen, verwenden SPIM oder MARS, normalerweise ohne Verzweigungsverzögerungsschlitze. (Im Gegensatz zu echtem MIPS müssen Sie den Compiler entsprechend anpassen nicht Nutzen Sie die nächste Anweisung nach einer bedingungslosen Verzweigung, selbst wenn sie ausgeführt wird.) Für GCC ist die Option -fno-delayed-branch – das wird jeden Verzögerungsschlitz mit einem NOP füllen, sodass der Code weiterhin auf einem echten MIPS ausgeführt wird. Sie können einfach alle NOPs manuell entfernen.

Möglicherweise sind weitere Optimierungen erforderlich, z. B. MARS, die Sie möglicherweise verwenden müssen jr $31 Anstatt von j $31, Optimieren Sie die mips-gcc-Ausgabe, um mit MARS zu arbeiten. Und natürlich muss I/O-Code mit implementiert werden Das Spielzeugsystem von MARS ruftnicht jal Aufrufe von Standardbibliotheksfunktionen wie printf oder std::ostream::operator<<. Sie können asm jedoch sinnvoll kompilieren (und von Hand optimieren), um Daten zu manipulieren, z. B. Ganzzahlen zu multiplizieren oder ein Array zu summieren oder umzukehren.

Leider hat GCC keine Möglichkeit, Registernamen wie z $a0 Anstatt von $r. Für PowerPC gibt’s -mregnames benutzen r1 Anstatt von 1aber keine ähnliche Option für MIPS, um “symbolischere” Registrierungsnamen zu verwenden.

int maybe_square(int num) {
    if (num>0)
        return num;
    return num * num;
}

Auf Godbolt mit GCC 5.4 -xc -O3 -march=mips32r2 -Wall -fverbose-asm -fno-delayed-branch

-xc kompiliert als C, nicht als C++, weil ich das bequemer finde, als in der Dropdown-Liste zwischen den Sprachen C und C++ zu wechseln und die Site meinen Quellcode löschen zu lassen.

-fverbose-asm kommentiert das asm mit C-Variablennamen für das Ziel und die Quellen. (In optimiertem Code ist das oft ein erfundenes Temporär, aber nicht immer.)

-O3 aktiviert die vollständige Optimierung, da die Standardeinstellung -O0 Der Debug-Modus ist für Menschen ein schreckliches Durcheinander. Verwenden Sie immer mindestens -Og wenn Sie sich den Code von Hand ansehen und sehen möchten, wie er die Quelle implementiert. Wie entferne ich “Rauschen” aus der GCC/Clang-Assembly-Ausgabe?. Sie könnten auch verwenden -fno-unroll-loopsund -fno-tree-vectorize beim Kompilieren für eine ISA mit SIMD-Anweisungen.

Dies nutzt mul anstelle des klassischen MIPS mult + mfloDanke an die -march= Option, um GCC mitzuteilen, dass wir für eine spätere MIPS-ISA kompilieren, unabhängig von der Standard-Baseline. (Vielleicht MIPS I alias R2000, -march=mips1)

Siehe auch den Abschnitt im GCC-Handbuch MIPS-Zieloptionen.

# gcc 5.4 -O3
square:
        blez    $4,$L5
        nop
        move    $2,$4    # D.1492, num         # retval = num
        j       $31                            # jr $ra  = return
        nop

$L5:
        mul     $2,$4,$4   # D.1492, num, num   # retval = num * num
        j       $31                             # jr $ra  = return
        nop

Oder mit Klirren, verwenden -target mips um es anzuweisen, für MIPS zu kompilieren. Sie können dies auf Ihrem Desktop tun; Im Gegensatz zu GCC wird Clang normalerweise mit mehreren aktivierten Back-Ends erstellt.

Von demselben Godbolt-Link klingelt 10.1 -xc -O3 -target mips -Wall -fverbose-asm -fomit-frame-pointer. Das Standardziel ist anscheinend MIPS32 oder so ähnlich für Clang. Außerdem aktiviert clang standardmäßig Rahmenzeiger für MIPS, wodurch asm verrauscht wird.

Beachten Sie, dass es sich für asm ohne Verzweigung entschieden hat, indem es eine if-Konvertierung in eine bedingte Bewegung durchführt, um zwischen der ursprünglichen Eingabe und dem mul-Ergebnis auszuwählen. Leider wird clang nicht unterstützt -fno-delayed-branch; vielleicht hat es einen anderen Namen für dieselbe Option, oder vielleicht gibt es keine Hoffnung.

maybe_square:
        slti    $1, $4, 1
        addiu   $2, $zero, 1
        movn    $2, $4, $1            # conditional move based on $1
        jr      $ra
        mul     $2, $2, $4            # in the branch delay slot

In diesem Fall können wir einfach die mul Vor dem jr, aber in anderen Fällen ist die Konvertierung in asm ohne Verzweigungsverzögerung nicht ganz trivial. zB Verzweigung auf einem Schleifenzähler Vor das Dekrementieren kann nicht rückgängig gemacht werden, indem das Dekrement an erster Stelle steht; das würde die bedeutung ändern.


Namen registrieren:

Compiler verwenden Registernummern und kümmern sich nicht um Namen. Für den menschlichen Gebrauch werden Sie oft zurückübersetzen wollen. Viele Orte im Internet haben MIPS-Registertabellen, die zeigen, wie $4..$7 $a0..$a3 sind, $8.. $15 sind $t0.. $t7 usw. Zum Beispiel Dieses hier.

Benutzer-Avatar
Fluss

Sie sollten einen Cross-Compiler aus den Ubuntu-Repositories installieren. GCC MIPS C Cross-Compiler sind in den Repositories verfügbar. Wählen Sie nach Ihren Bedürfnissen:

  • gcc-mips-linux-gnu – 32-Bit-Big-Endian.
  • gcc-mipsel-linux-gnu – 32-Bit-Little-Endian.
  • gcc-mips64-linux-gnuabi64 – 64-Bit-Big-Endian.
  • gcc-mips64el-linux-gnuabi64 – 64-Bit-Little-Endian.
  • usw.

(Hinweis für Benutzer von Ubuntu 20.10 (Groovy Gorilla) oder höher und Debian-Benutzer: Wenn Sie normalerweise Ihre regulären Compiler mit der build-essential Paket, würden Sie gerne wissen, ob es existiert crossbuild-essential-mips, crossbuild-essential-mipsel, crossbuild-essential-mips64eletc.)

In den folgenden Beispielen gehe ich davon aus, dass Sie die 32-Bit-Little-Endian-Version gewählt haben (sudo apt-get install gcc-mipsel-linux-gnu). Die Befehle für andere MIPS-Versionen sind ähnlich.

Um mit MIPS anstelle der nativen Architektur Ihres Systems umzugehen, verwenden Sie die mipsel-linux-gnu-gcc Befehl statt gcc. Zum Beispiel, mipsel-linux-gnu-gcc -fverbose-asm -S myprog.c erzeugt eine Datei myprog.s enthält MIPS-Assembly.

Eine andere Möglichkeit, die MIPS-Assembly anzuzeigen: run mipsel-linux-gnu-gcc -g -c myprog.c um eine Objektdatei zu erzeugen myprog.o die Debugging-Informationen enthält. Zeigen Sie dann die Disassemblierung der Objektdatei mit an mipsel-linux-gnu-objdump -d -S myprog.o. Zum Beispiel, wenn myprog.c ist das:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    printf("The answer is: %d\n", a + b);
    return 0;
}

Und wenn es mit kompiliert wird mipsel-linux-gnu-gcc -g -c myprog.cdann mipsel-linux-gnu-objdump -d -S myprog.o wird so etwas zeigen:

myprog.o:     file format elf32-tradlittlemips


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main() {
   0:   27bdffd8    addiu   sp,sp,-40
   4:   afbf0024    sw  ra,36(sp)
   8:   afbe0020    sw  s8,32(sp)
   c:   03a0f025    move    s8,sp
  10:   3c1c0000    lui gp,0x0
  14:   279c0000    addiu   gp,gp,0
  18:   afbc0010    sw  gp,16(sp)
    int a = 1;
  1c:   24020001    li  v0,1
  20:   afc20018    sw  v0,24(s8)
    int b = 2;
  24:   24020002    li  v0,2
  28:   afc2001c    sw  v0,28(s8)
    printf("The answer is: %d\n", a + b);
  2c:   8fc30018    lw  v1,24(s8)
  30:   8fc2001c    lw  v0,28(s8)
  34:   00621021    addu    v0,v1,v0
  38:   00402825    move    a1,v0
  3c:   3c020000    lui v0,0x0
  40:   24440000    addiu   a0,v0,0
  44:   8f820000    lw  v0,0(gp)
  48:   0040c825    move    t9,v0
  4c:   0320f809    jalr    t9
  50:   00000000    nop
  54:   8fdc0010    lw  gp,16(s8)
    return 0;
  58:   00001025    move    v0,zero
}
  5c:   03c0e825    move    sp,s8
  60:   8fbf0024    lw  ra,36(sp)
  64:   8fbe0020    lw  s8,32(sp)
  68:   27bd0028    addiu   sp,sp,40
  6c:   03e00008    jr  ra
  70:   00000000    nop
    ...

Sie müssten die Quelle in binutils und gcc-core herunterladen und mit etwas wie kompilieren ../configure --target=mips .... Möglicherweise müssen Sie ein bestimmtes MIPS-Ziel auswählen. Dann könnten Sie verwenden mips-gcc -S.

  • kannst du bitte etwas mehr erklären. Ich muss auch von C nach MIPSR3000 konvertieren.

    – Shankhadeep Mukerji

    29. November 2016 um 9:31 Uhr

  • @ShankhadeepMukerji Schau mal gcc.gnu.org/install . Sehen Sie sich unter Schritt 3 die „Sollspezifikation“ an.

    – Ben Jackson

    29. November 2016 um 20:20 Uhr

Benutzer-Avatar
Nils Pipenbrink

Sie können den GCC crosskompilieren, sodass er MIPS-Code anstelle von x86 generiert. Das ist eine schöne Lernerfahrung.

Wenn Sie schnelle Ergebnisse wünschen, können Sie auch einen vorgefertigten GCC mit MIPS-Unterstützung erhalten. Eine davon ist die CodeSourcery Lite Toolchain. Es ist kostenlos, kommt für viele Architekturen (einschließlich MIPS) und sie haben gebrauchsfertige Binärdateien für Linux und Windows.

http://www.codesourcery.com/sgpp/lite/mips/portal/[email protected]=lite

  • kannst du bitte etwas mehr erklären. Ich muss auch von C nach MIPSR3000 konvertieren.

    – Shankhadeep Mukerji

    29. November 2016 um 9:31 Uhr

  • @ShankhadeepMukerji Schau mal gcc.gnu.org/install . Sehen Sie sich unter Schritt 3 die „Sollspezifikation“ an.

    – Ben Jackson

    29. November 2016 um 20:20 Uhr

Benutzer-Avatar
Jack

Sie sollten Ihre eigene Version von gcc kompilieren, die crosskompiliert werden kann. Das ist natürlich nicht einfach, also könntest du nach einem anderen Ansatz suchen, zum Beispiel Dies SDK.

1256310cookie-checkGibt es eine Möglichkeit, gcc zu verwenden, um C in MIPS zu konvertieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy