% Uebung2, Aufgabe 6 % % Dieses Rahmenprogramm enhält die Eingabe einer Zeichenkette über die Standard-Eingabe % und das Unwandeln in eine Zahl. Sollten nichtnumerische Zeichen eingegeben werden, % wird eine Fehlermeldung ausgegeben und das Programm beendet. % % Falls Warnungen beim Assemblieren auftreten, dann den Parameter -b 200 benutzen. % mmixal -b 200 rahmen.mms LOC Data_Segment GREG @ Bufsize IS 6 % Anzahl der Zeichen, die eingelesen werden sollen Parameter OCTA 0,Bufsize % An die erste Stelle wird später die Speicheradresse des Buffers abgelegt. % Die zweite Stelle steht für die Anzahl der Zeichen, die eingelesen werden sollen. Buffer BYTE 0,0 % Buffer für die Eingabe anlegen LOC @+Bufsize+1 % Speicherplatz für den Buffer reservieren newline BYTE #a,0 % ein newline-Zeichen mit String-Terminator % Texte für die Ausgabe anlegen Request BYTE "Bitte gib eine Zahl zwischen 1..10000 ein: ",0 IsPrim BYTE "Es handelt sich um eine Primzahl",#a,0 NotPrim BYTE "Ist keine Primzahl",#a,0 ErrZahlTxt BYTE "Bei der Eingabe handelt es sich nicht um eine Zahl!",#a,0 ErrRangeTxt BYTE "Die eingegebene Zahl befindet sich nicht im Bereich 1..10000!",#a,0 LOC #100 ParamAddr IS $1 % Speicheradresse der Parameter BufferAddr IS $2 % Speicheradresse des Buffers zahl IS $3 % umgewandelte Zahl char IS $4 % Adresse eines einzelnes Zeichen vom Buffer tmp IS $5 % Hilfsvariable zum Speichern vom Vergleichswert i IS $6 % Laufvariable max IS $7 % für den Primzahlentest rest IS $8 % zum Zwischenspeichern des Divisionsrests % % Hier wird von der Standardeingabe eingelesen und in Buffer gespeichert % Main LDA $255,Request % Adresse der Anfrage an den Nutzer holen TRAP 0,Fputs,StdOut % Text ausgeben LDA ParamAddr,Parameter % Adresse des Parameters laden LDA BufferAddr,Buffer % Adresse des Buffers laden STOU BufferAddr,ParamAddr,0 % Buffer-Adresse an die erste Stelle vom OCTA des Parameters speichern SET $255,ParamAddr % speichere die Adresse von Parameter ins globale Register $255 TRAP 0,Fgets,StdIn % von der Standardeingabe einlesen % % die Zeichenkette in Buffer wird nun in eine Zahl umgewandelt % SET i,0 % Laufvariable mit 0 initialisieren SET zahl,0 % Zahl mit 0 initialisieren Loop LDB char,BufferAddr,i % lade i-tes Zeichen (wir fangen bei 0 an!) BZ char,endloop % prüfe auf terminierendes Zeichen (0) -> springe zum Schleifenende CMP tmp,char,#a % prüfe, ob Zeichen ein Zeilenumbruch ist BZ tmp,endloop % wenn ja, springe zum Schleifenende % Es wird nun überprüft, ob sich das aktuelle Zeichen im ASCII-Bereich % zwischen 48 (der '0') und 57 (der '9') befindet. CMP tmp,char,'0' % Vergleiche char mit dem ASCII-Zeichen '0' BN tmp,ErrorZahl % falls das Zeichen kleiner 48 -> keine Zahl, springe zur Fehlerausgabe CMP tmp,char,'9' % Vergleiche nun mit ASCII-zeichen '9' BP tmp,ErrorZahl % falls das Zeichen größer 57 -> keine Zahl, springe zur Fehlerausgabe % das aktuelle Zeichen ist im ASCII-Bereich 48-57 % es werden nun 48 abgezogen, um die richtige Ziffer zu besitzen SUB char,char,48 MUL zahl,zahl,10 % unsere Ergebnis-Zahl wird erst mit 10 multipliziert ADD zahl,zahl,char % und anschließend die eben konvertierte Ziffer hinzuaddiert (Horner-Schema) ADD i,i,1 % erhöhe die Zählvariable JMP Loop % springe zum Schleifenanfang ErrorZahl LDA $255,ErrZahlTxt % Fehlernachricht ins globale Register speichern TRAP 0,Fputs,StdOut % Fehlernachricht ausgeben TRAP 0,Halt,0 % beende Programm % % Überprüfung, ob die eingegebene Zahl im Bereich 1..10000 liegt % endloop CMP tmp,zahl,1 % zahl mit 1 vergleichen BN tmp,ErrRange % Zahl ist kleiner als 1 -> Fehler ausgeben SET tmp,10000 % Umweg über tmp gehen, weil 10000 zu groß ist für den 3.Operand von CMP CMP tmp,zahl,tmp % zahl mit 10000 vergleichen BP tmp,ErrRange % Zahl ist größer als 10000 -> Fehler ausgeben % % Hier kommt der Primzahlentest rein % Das was hier steht kann durch eigenen Quellcode ersetzt werden. % SET i,2 % wir beginnen bei i = 2 SET max,zahl % diese Zeile ist nur ein Beispiel % TODO: % Eine Schleife, die die Zahl 'zahl' von i = 2 bis max teilt und % den Divisionsrest überprüft. % Außerdem muss noch eine Textausgabe von IsPrim und NotPrim eingebaut werden. % Hinweis: der Fall zahl = 1 muss gesondert behandelt werden... DIV tmp,zahl,i % Zahl durch i teilen GET rest,rR % und den Divisionsrest holen % jetzt müsste der Divisionsrest geprüft werden ... TRAP 0,Halt,0 % beende Programm % hier kommt noch eine Ausgabe von einer Fehlernachricht ErrRange LDA $255,ErrRangeTxt % Fehlernachricht ins globale Register speichern TRAP 0,Fputs,StdOut % Fehlernachricht ausgeben TRAP 0,Halt,0 % beende Programm