MIPS CPU (und keiner von einer anderen gemeinsamen eins) haben keine „strings vergleichen“ Anweisung, string ist nicht nativen CPU-Typ und die Anweisungen beschäftigen nur mit einheimischen Arten, wie Worte und Bytes.
"Zeichenfolge" ist eine bestimmte Anzahl (aufeinanderfolgend definierter Zeichen oder die Verwendung eines Abschlusszeichens am Ende der Daten) aufeinanderfolgender Zeichen. Was "ein Zeichen" ist, hängt von der verwendeten Kodierung ab, in Ihrem Fall (MARS-Simulator und einfaches Üben der ASM-Programmierung) können Sie bei der alten ASCII-Kodierung bleiben, wobei ein einzelnes Zeichen genau ein einzelnes Byte ist. (JFYI: Mit moderner SW werden Sie hauptsächlich in UTF8 Kodierung arbeiten, wie diese Webseite, wo einzelne Zeichen unterschiedliche Anzahl von Bytes haben können, abhängig davon, welche Glyphe Sie kodieren, was die Programmierung eines beliebigen String-Algorithmus über UTF8-kodierten String viel mehr Spaß macht als Ihre aktuelle Aufgabe.Ziemlich oft zu viel Spaß.)
Nun wie die CPU-Register sind "Wort" Größe, das bedeutet, sie sind 32 Bits "breit", dh sie können maximal 4 ASCII-Zeichen auf einmal (4 Bytes), so dass die Verwendung von Registern zum Speichern ganzer Strings nur für sehr sho möglich wäre. str. und sonst nichts. Sie können das tun, aber es ist nicht praktisch (außer die beq
würde funktionieren, weil Sie Word-Wert 0x30303030
= "0000"
gegen 0x31313131
= "1111"
mit beq
vergleichen können).
Also die meiste Zeit während der Programmierung in MIPS Anfänger Assembly die "Strings" folgen Muster: einige Register enthält Speicheradresse zeigt auf den ersten Buchstaben der Zeichenfolge (erstes Byte der Zeichenfolge), und die allerletzte "Zeichen" von String ist kein Buchstabe, sondern der Wert Null, der sogenannte "Null-Terminator".
Wenn Sie Zeichenfolgen dann vergleichen möchten, erstellen Sie Schleife, die mit zwei Zeigern (zu den zwei Zeichenfolgen = zu den ersten beiden Buchstaben) beginnt. Lade das Byte von beiden Adressen in ein temporäres Register (d. H. Lade den ersten Buchstaben von beiden), vergleiche das, und, falls sie sich unterscheiden, unterscheiden sich die Strings. Wenn Sie gleich sind, prüfen Sie auf Null (beide Strings beendet = sie sind gleich). Wenn nicht Null, führe beide Adressen um eins weiter, so dass sie auf den nächsten Buchstaben zeigen und zum Anfang zurückkehren.
Aber in Ihrem Fall kann der Benutzer nur einzelnen Buchstaben eingeben, und Sie möchten nur einzelne Buchstaben zu vergleichen, so schreiben ganze Schleife ist eine Art reichlich Aufwand, können Sie nur diesen einzelnen Buchstaben laden und vergleichen Sie das.
So lesen Sie Ihre Quelle von oben, werden diese Zeilen von mir bekommen:
#li $a1, 2
wird kommentiert, warum? Sie sollten das verwenden, um den Syscall zu begrenzen (ich denke, ohne irgendeinen Wert zu setzen, kann der Standardwert Null sein, so dass keine Eingabe stattfindet). Vielleicht interessiert Sie auch syscall(v0=12) "Lesezeichen" anstelle von "Lesezeichenfolge", aber ich bin mir nicht sicher, wie das für Benutzer in MARS dargestellt wird (User Experience bezogen), aber bleiben wir beim Service v0 = 8 "read string" und 2 Byte langer Puffer.
Jetzt, nachdem syscall
zurückkehrt (der Benutzer hat den Buchstaben "f" eingegeben), enthält der Speicher unter der Adresse space
zwei Bytes, die von syscall: 102, 0 gesetzt wurden.
li $t1, 102
kommt mir bekannt vor, aber schwierig für andere Programmierer zu lesen, mit MARS Assembler können Sie verwenden, auch auf diese Weise, dass die Anzahl der Schreiben: li $t1, 'f'
- die einfache Apostrophe sagt Ihnen Wert einzelner ASCII-Zeichen Assembler wollen ('ab'
fehler in MARS können nur einzelne Zeichen verwendet werden, einige andere Monteuren die ‚ab‘ als zwei Byte-Wert)
Weiter uncommented Anweisung kann übersetzen:
syscall
Und hier sind Sie gefragt, für die MA RS-Dienst? Sie haben keinen Wert in v0
gesetzt, noch benötigen Sie einen Dienst. Wenn Sie also Ihren Code im Debugger einmal übergehen würden, sollte das für Sie keinen Sinn ergeben, wenn Sie sich überlegen, was mit jeder Anweisung passiert.
Dann kommt .
An diesem Punkt der t1
zu 'f'
gleich ist, und t0
gleich Adresse des ersten Bytes des Puffers, der auch als space
Symbol während der Kompilierung aliased, die zu einem gewissen 32-Bit-Wert ist, wahrscheinlich ähnlich wie etwas wie 0x100000c
. Die Werte 0x100000c
vs 102
sind sicherlich nicht gleich, so dass beq
niemals auf das Label fahrenheit
springen wird.
Um diese Anfangsbuchstabe innerhalb Puffer zu vergleichen, zunächst seinen Wert aus dem Speicher holen, wie lb $t2, ($t0)
, dass Lasten Wert von Adresse in t0
(erweiterte Info-Byte:. lb
den 8-Bit-Wert auf 32-Bit-Wert Vorzeichen erweitern Grund bedruckbaren Zeichen von ASCII sind alle kleiner als 128, so dass Sie keine negativen Werte verarbeiten müssen. Wenn der Buchstabe 'f' jedoch als 140 codiert würde, würde zum Laden dieses Werts in t2
den 32-Bit-Wert -116
und nicht 140
ergeben. Wie ich geschrieben habe, ist das grundlegende ASCII nur 7 Bit, also nur positive Werte, die wie erwartet funktionieren, 102 wird geladen als 102).
Dann können Sie mehr Erfolg mit beq $t2, $t1, fahrenheit
haben, da jetzt ASCII-Zeichen gegen ASCII-Zeichen verglichen werden.
Sie können auch MARS MIPS Assembly-Pseudobefehl beq $t2, 'f', fahrenheit
verwenden. MARS wird, dass als zwei native Befehle kompilieren:
addi $at, $zero, 102 # 102 = 'f', $at = $1, $zero = $0
beq $at, $t2, fahrenheit
Sie etwas Tipp Speichern, die in der Programmierung ist gut, solange es Sinn macht beim Lesen (wenn Sie Ihren Quellcode zu verkürzen beginnt nur zum Zweck der Kurzes Schreiben, du machst es falsch, bei der Programmierung wird der Quellcode geschrieben, um gelesen zu werden, die Schreibkosten sind im Vergleich zu den Lesekosten vernachlässigbar). In diesem Fall sieht beq $t2, 'f', label
für mich ziemlich gut aus, also würde ich das bevorzugen.
Und das sollte genug sein, um beide Fragen zu beantworten, die explizite (wie Strings = in einer Schleife, Zeichen für Zeichen zu vergleichen), und die implizite (wie man diesen einzelnen Buchstaben von Benutzer mit 'f' vergleichen).
Haben Sie Ihren Code im eingebauten Debugger einmal durchgegangen? Haben Sie in den Dokumenten nach dem von Ihnen verwendeten Syscall gesucht, um festzustellen, ob ein Zeichen in einem Register zurückgegeben wird oder ob es im Speicher gespeichert ist? Sie könnten einen Zeiger mit einer Zahl oder etwas vergleichen. (Sie haben Ihren Code nicht kommentiert, und ich kenne die MIPS-Simulator-Systemnummern nicht von ganz oben.) Wie auch immer ** benutze den Debugger **, es wird es so viel einfacher machen in der Lage zu sein zu überprüfen, was eigentlich in jedem Register ist, das 'beq' betrachtet. –