2017-10-23 8 views
0

Also habe ich Code geschrieben, der eine Zeichenfolge vom Benutzer in einem Format übernimmt, in dem das erste Zeichen ein nicht numerisches ist und der Rest Zahlen sind. Mein Code entfernt das erste Zeichen und speichert die verbleibenden Zahlen in einer Variablen. Jetzt versuche ich eine Konstante (Beispiel 5) zu den restlichen Zahlen hinzuzufügen und auszudrucken. Ich bin mir nicht sicher, was falsch läuft.MIPS druckt eine Adresse anstelle des Wertes an dieser Adresse

.data 

    string: .asciiz  "Enter a string:\n" 
    string1: .asciiz   "The value +5 is:\n" 
    inputString: .space 20 
    outInt: .word 0 
    int5: .word 5 
    addedInt: .word 0 


.text 

main: 

    #print initial string to console insruction 4 
    li $v0, 4 
    la $a0, string 
    syscall 

    #get first string from user 
    li $v0, 8 
    la $a0, inputString 
    li $a1, 8  #a1 contains max length of string to be entered 
    la $t0, ($a0) 
    syscall 

    addiu $t0, $t0, 1 #remove first letter 

    li $v0, 4  #prints out remaining numbers without leading character 
    la $a0, ($t0) 
    syscall 

    sw $a0, outInt #store new word in outInt 


    lw $t0, outInt #print out outInt to check if its correct 
    la $a0, ($t0) 
    syscall 

    lw $t1, int5 
    add $t2, $t0, $t1 #add 5 to the remaining numbers 

    sw $t2, addedInt #store result 
    li $v0, 4 
    la $a0, string1 #print the value + 5 string 
    syscall 

    li $v0, 1 #output a number (not a string) 
    lw $a0, addedInt 


    syscall 

    jr $ra 

Der Ausgang, wenn ich die Zeichenfolge "X123" einzugeben:

eine Zeichenfolge eingeben:

X123

Der Wert 5 ist:

268.501.033

+0

Was * sollte * die Ausgabe sein, und warum? –

+0

Die Ausgabe sollte 128 sein (weil 123 + 5 = 128). Es ist für eine Aufgabe. –

+0

Was sehen Sie in Registern, wenn Sie den Debugger verwenden, um den Code in einem Schritt zu bearbeiten? –

Antwort

0

Was Ihr Code macht:

Eingänge String in 20-Byte-Pufferspeicher an der Adresse inputString (die 268501027 unter MARS passiert zu sein, die wie Sie beim Laufen genau gleiche Zuweisung aussieht).

Wenn der Benutzer "X123" eingibt, dann sehen die Bytes im Speicher so aus: 58 31 32 33 0A 00 00 00 ... (hat nicht herausgefunden, wie man Speicher pro Byte in MARS anzeigt, also muss man verstehen, wie Little-Endian funktioniert, und wie diese in MARS angezeigten Wortwerte auf bestimmte einzelne Bytes reduziert werden können), 0x58 ist der ASCII-Code für den Buchstaben X, 0x31 ist der ASCII-Code für Buchstabe/Ziffer 1 usw. ... 0x0A ist das Newline-Zeichen (Teil der Eingabe!), Die verbleibenden Nullen sind Ihr Glück, dass MARS Ihnen am Anfang der Ausführung des Codes das zero .data-Segment zur Verfügung stellt, so dass Ihre nächste Ausgabe der Benutzerzeichenfolge korrekt null-terminiert ist (und auch newline).

Dann Sie Ausgabezeichenfolge von Adresse inputString+1, die, dass die Punkte auf 0x31 = ASCII-Code für digit '1', und die restlichen von Benutzereingabe folgt, so dass die erwartete (?) String "123 \ n" ausgegeben wird. Beachten Sie, dass "ersten Buchstaben entfernen" nichts vom Gerät entfernt, sondern nur den Zeiger anpasst, der dann als "Anfang" der Zeichenfolge verwendet wird. Wenn Sie den Brief im selben Speicherbereich tatsächlich entfernen, müssen Sie Byte für Byte den gesamten Buchstaben an die vorherige Adresse kopieren, was eine wesentlich teurere Operation ist, und dann den einzelnen Zeiger um eins anpassen.

sw $a0, outInt  #store new word in outInt 

Diese speichert die Adresse outInt268501028 in Speicherwort bei der Adresse eingestellt. Es speichert das Wort nicht selbst. Auch hier findet keine Umwandlung von String in int statt. Alles, was Sie tun, ist nur speichern Sie den Zeiger (Speicheradresse), die 268501028. 32b unsigned integer ist

Dann Sie ohne v0 Argument ausdrücklich besagt, neben syscall nennen so 4 der vorherige Wert wird wiederverwendet, wieder zur Ausgabe string, von der gleichen Adresse, so wieder erhalten Sie die gleiche Ausgabe "123\n". Ich würde empfehlen, immer die v0 vor jeder syscall explizit festzulegen, auch wenn es der gleiche Wert ist, der bereits in Register ist, erleichtert das Lesen der Quelle beim Debuggen im Kopf und Überprüfen.

Schließlich laden Sie Wert 5 in t1 und daß 268501028 zu dieser Adresse hinzuzufügen, die in ganzzahligen 268501033 führt, und zu speichern, dass in dem Speicher an der Adresse addedInt. Dann drucken Sie das Label +5 aus und laden diesen Wert zurück in a0 und drucken es aus.

Sie sollten den eingebauten Debugger des MARS/SPIM-Familiensimulators, den Sie verwenden, verwenden, um die Anweisungen zu übergehen und die Registerwerte und den Speicherinhalt zu sehen und diese mit meiner Beschreibung zu vergleichen, um zu verstehen, was diese Anweisungen tatsächlich bedeuten machen.

fix:

„zu breit“, im Grunde müssen Sie entweder:

a) das Benutzer-String in Integer-Wert zu konvertieren: mit Schreiben der Eingangslade Buchstaben, bis Sie entweder Newline-Zeichen oder Null-Terminators erreichen Umwandeln von Ziffern in Werte (ASCII_code - '0') == digit_value, dann Berechnen der temporären Summe, wie sum = sum*10 + digit_value, beginnend mit sum = 0. Am Ende der Schleife enthält sum den Wert 123 (aus der Zeichenfolge "123"). Dann können Sie 5 als Ganzzahl hinzufügen (Wert 128 erhalten) und syscall, v0=1 verwenden, um es auszugeben.

b) Addieren Sie den Wert 5 über die Zeichenfolge, dh die Adresse von Newline/Zero-Terminator, dann um 1 zurück. Sie haben die Adresse der letzten Ziffer (wenn die Eingabe gültig ist!) Um Adresse inputString zu adressieren, und wenn Adresse gültig ist, können Sie auch überprüfen, Inhalt in Bereich '0' = 0x30 .. '9' = 0x39, dh, dass der Inhalt ASCII-Ziffer-Brief ist Dann Schleife: 1) 5 zum aktuellen Buchstaben hinzufügen 2) wenn Ergebnis <= '9' ist , dann sieht die Zeichenfolge wie Zahl aus und Sie können sie ausgeben (Verzweigung zur Ausgabe mit inputString+1 Adresse zur Anzeige). 3) subtrahiere 10 davon (d. H. '7'+5 = 60 = '<', dann 60 - 10 = 50 = digit-letter '2') 4) dekrementiere die Adresse um 1 (Bewegung um eine Position nach links) 5) bestätige die Adresse. 6) check Inhalt: Wenn nicht Ziffer, überschreiben Sie es mit dem Buchstaben '1' und zum Ausgang von Adresse dieser '1' (mit gültiger Eingabe wie "X99", die gleich inputString sein wird, und der Speicher wird modifizierte Zeichenfolge enthalten "104"), wenn Ziffer, hinzufügen Eins dazu und zu Schritt 2 springen) - prüfen, ob der resultierende Wert <= '9' ist.

Und das ist es, das ist "Hinzufügen von 5", wenn Sie nicht über ganzzahlige Werte, sondern über ASCII-Zeichen im Speicher arbeiten. Das hört sich vielleicht nach viel Arbeit an, aber in Variante a) ist es möglicherweise einfacher zu schreiben und zu debuggen als die Konvertierung von String zu Int.

Schließlich sollten Sie wahrscheinlich versuchen, beide Varianten zu schreiben, nur um zu verstehen, wie grundlegende Datentypen in Assembly funktioniert, und was ist der Unterschied zwischen "Zeichenfolgen" und Ganzzahlen (und Byte- und Wortwerte) und wie Speicheradressierung funktioniert .

Verwandte Themen