% Mögliche Lösung zu Uebung2, Aufgabe 6 (Primzahlentest) von Matthias Dräger % % Dieses Programm fordert den Benutzer auf eine Zahl zw. 1 und 10.000 einzugeben. % Die Eingabe wird in eine Zahl konvertiert und geprüft. Der Primzahlentest sieht % wie folgt aus: % - wurde 1 eingegeben -> gib "keine Primzahl" aus % - wurde 2 eingegeben -> gibt "Primzahl" aus % - mit einer Schleife von 2 bis Zahl/2 wird die Teilbarkeit von Zahlen > 2 geprüft % % 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 % % Pre-Test vor dem eigentlichen Primzahlentest % CMP tmp,zahl,1 % ist die eingegebene Zahl 1? BZ tmp,IstKeinPrim % -> keine Primzahl CMP tmp,zahl,2 % ist die eingegebene Zahl 2? BZ tmp,IstPrim % -> keine Primzahl % % Hier beginnt der eigentliche Primzahlentest % SET i,2 % wir beginnen bei i = 2 DIV max,zahl,2 % und prüfen Teilbarkeit bis Zahl/2 bWhile DIV tmp,zahl,i % Zahl durch i teilen GET rest,rR % und den Divisionsrest holen BZ rest,IstKeinPrim % wenn Rest = 0 -> teilbar, also keine Primzahl ADD i,i,1 % Zählvariable um 1 erhöhen CMP tmp,i,max % vergleiche Laufvariable mit max PBNP tmp,bWhile % wenn i <= max, mache weiter % keinen Teiler gefunden? dann Erfolgreichnachricht ausgeben IstPrim LDA $255,IsPrim % Nachricht ausgeben, dass es eine Primzahl ist TRAP 0,Fputs,StdOut TRAP 0,Halt,0 % beende Programm IstKeinPrim LDA $255,NotPrim % Nachricht ausgeben, dass es KEINE Primzahl ist TRAP 0,Fputs,StdOut 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