### Demo-Programm für MIPS für die Vorlesung ###
###        "Grundlagen der Informatik"       ###
###               Jörg Roth                  ###
###
### primelist: Gebe alle Primzahlen bis zu einem Höchstwert aus.
### Dazu wird das Unterprogramm primetest benutzt.
### Mit diesem Programm soll vor allem der Unterprogramm-Aufruf
### illustriert werden. Da primetest die Register $s0-$s5 benutzt,
### müssen diese von dem Unterprogramm gerettet werden.

###
### $s0:   Eingabe, Zahl bis zu der Primzahlen aufgelistet werden sollen (exklusiv)
### $s1:   Schleifenzähler

        .data

blank: .asciiz " "           # Blank wird zur Ausgabe der Liste benötigt

	.text

primetest:
     addi $sp,$sp,-24        # Auf dem Stapel Platz für 6 Register freimachen
     sw $s0,0($sp)           # Sichern aller Register $s0..$s5 auf dem Stapel
     sw $s1,4($sp)
     sw $s2,8($sp)
     sw $s3,12($sp)
     sw $s4,16($sp)
     sw $s5,20($sp)

     or $s0,$zero,$a0        # Das Argument (die zu testende Zahl) steht in $a0

     ### Hier beginnt die eigentliche Arbeit des Unterprogramms primetest ###

     li $s1, 1               # Ergebnis =1 (ist Primzahl) vorbelegen
     li $s2, 2               # Konstante 2 wird mehrfach benötigt
     beq $s0, $s2, end       # Vergleich mit 2 => Primzahl
     and $s3, $s0, 1         # Alle Bits bis auf das letzte ausmaskieren
     beq $s3, $zero, noprime # Letztes Bit war 0, also gerade => keine Primzahl

     ### An dieser Stelle muss es sich um eine ungerade Zahl handeln ###

     beq $s0,$s1, noprime    # Vergleich mit 1 => keine Primzahl
     srl $s3, $s0,1          # 1 Mal Shiften, d.h. durch 2 teilen
     li $s4, 3               # 3 ist die erste Zahl durch die geteilt wird
loop:
     sltu $s5,$s4,$s3        # $s4=0 wenn $s4>=$s3, 
     beq $s5,$zero,end       # d.h. wir haben x/2 erreicht => Primzahl
     div $s0,$s4             # Es wird auf Teilbarkeit geprüft
     mfhi $s5                # $s5 ist Teilerrest
     beq $s5,$zero,noprime   # Der Teilungsrest war 0 => keine Primzahl
     addi $s4,$s4,2          # Die Schleifenvariable wird um zwei erhöht
     j loop                  # Erneut testen

noprime:
     li $s1, 0               # Ergebnis =0 (keine Primzahl)
end: 
     ### Hier endet die eigentliche Arbeit des Unterprogramms primetest ###

     or $v0,$zero,$s1        # Der Rückgabewert steht in $v0 

     lw $s0,0($sp)           # Zurücklesen aller Register $s0..$s5 von dem Stapel
     lw $s1,4($sp)
     lw $s2,8($sp)
     lw $s3,12($sp)
     lw $s4,16($sp)
     lw $s5,20($sp)
     addi $sp,$sp,24         # Stapelzeiger auf Wert vor dem Aufruf setzen

     jr $ra                  # Rücksprung zum Aufrufer

main:
     li $v0, 5               # Eingabe einlesen
     syscall
     or $s0, $zero, $v0      # $s0 := Eingabe

### Hier beginnt Erstellung der Liste ###

     li $s1, 0               # Wir beginnen die Schleife mit 0
mainloop:
     or $a0, $zero, $s1      # Schleifenvariable $s1 als Parameter übergeben
     jal primetest           # Unterprogramm primetest aufrufen
     beq $v0,$zero,noprint   # wenn Rückgabewert $v0=0 war es keine Primzahl, daher Ausgabe überspringen

### Syscalls zur Ausgabe der Primzahl ###
     li $v0, 1               # Resultat ausgeben
     or $a0, $zero, $s1      # in $s1 stand die Primzahl
     syscall
     li $v0, 4               # String ausgeben
     la $a0,blank            # Nur ein Blank
     syscall
### Syscalls zur Ausgabe der Primzahl Ende ###
 
noprint:
     addi $s1,$s1,1          # Um 1 erhöhen 
     bne $s0,$s1,mainloop    # Wenn Ende noch nicht erreicht: Schleife

### Ende der Erstellung der Liste ###

