Frage in Assembler Code mit MIPS



  • Hallo an Alle,
    Lerne grad Assemblerprogrammierung mit dem MIPS-Simulator und versuche ein kleines Prog zu schreiben, leider komme ich nicht weiter.
    Mein Ziel ist ein kleines prog zu schreiben, was Zahlen richtig sortiert. Später will ich auf die sortierte Zahlen zugreifen können. Der Benutzer soll solange Zahlen eingeben, bis er die 0 tippt.
    Nachdem das passert ist sollen die Zahlen richtig sortiert werden.
    Da ich in C/C++ schon mal programmiert habe und da einwenig erfahrung hab, versuche ich den Bubble-sort-algo in assembler umzusetzen.
    Hier der Code..:

    .text		
    
    main:
    	addi $s0,$s0,0		# register $s0 bekommt die 0 zugewiesen ($s0=0)
    				# brauche das zum zählen der eingabe
    	addi $s2,$s2,1		# $s2 = 0 - brauche das für sort 
    	addi $s3,$s3,0		# $s3 = 0 - brauche das für print
    
    loop_str:
    	la  $a0,input_1     	# lade adresse von input_1 an register $a0 
    	li  $v0,4		# print Zeichenkete von register $a0
    	syscall
    	li  $v0,5		# Zahl von Konsole lesen und an register $v0 speichern
    	syscall
    	move $s1,$v0		# Zahl die von Konsole gelesen $v0 zu $s1 verschieben
    	beq  $s1,0, sort	# wenn die zahl gleich 0 ist --> gehe zu sort
    	sw $s1, ($sp)		# speichere die zahl im stack
    	addi $s0,$s0,1		# $s0 um 1 erhöhen, da der user eine eingabe gemacht hat
    	addi $sp,$sp,-4		# zeiger(stack-pointer) zeigt eine stelle weiter im stack
    	j loop_str		# wiederhole das ganze nochmal --> gehe zu loop_str
    
    sort:
    	mul $t0,$s0,4		# $t0 = $s0 * 4 - Anzahl der Elemente mal 4
    	add $sp,$sp,$t0
    
    sort_loop:
    
    	beq $s2,$s0,print	# wenn $s2 gleich $s0, dann gehe zu sort
    	lw $t1,($sp)		# erste zahl wird in $t1 gespeichert
    	addi $sp,$sp,-4		# zeiger zeigt auf die zweite zahl
    	lw $t2,($sp)		# zweite zahl wird in $t2 gespeichert
    	addi $s2,$s2,1		# $s2 += 1
    	blt $t2,$t1,replace	# wenn $t2 < $t1, dann vertausche die zahlen		
    	j sort_loop		# ...und das ganze nochmal
    
    replace:
    	addi $sp,$sp,4		# zeiger zeigt wieder auf der ersten zahl
    	sw $t2, ($sp)		# $t2 kommt an der ersten stelle
    
    	addi $sp,$sp,-4		# zeiger zeigt auf die zweite zahl
    	sw $t1, ($sp)		# $t1 kommt an der zweiten stelle
    
    	j sort_loop		# gehe zu sort_loop
    
    print:	la  $a0,print_txt 	# lade adresse von nl an register $a0
    	li  $v0,4		# print zeichenkette von $a0 --> also print
    	syscall
    	mul $t0,$s0,4		# $t0 = $s0 * 4 - Anzahl der Elemente mal 4
    	add $sp,$sp,$t0			 
    	addi $sp,$sp,-4		# zeiger zeigt auf die erste zahl
    print_loop:	
    	lw $a0, ($sp)		# lade die erste zahl vom stack und übergebe die an $a0
    	li $v0,1		# print dezimalzahl von $a0
    	syscall	
    	addi $s3,$s3,1		# $s3 += 1
    	la  $a0,nl     	 	# lade adresse von nl an register $a0
    	li  $v0,4		# print zeichenkette von $a0 --> also \n
    	syscall
    	beq $s3,$s0, Exit	# wenn $s3=$s0 ist ---> gehe zu Exit
    	addi $sp,$sp,-4		# zeiger eine stelle zurücksetzen
    	j print_loop		# das ganze wiederholen...
    
    Exit:		
    	li $v0,10		# EXIT
    	syscall 
    
    .data
    input_1: 	.asciiz 	"Bitte eine Zahl eingeben..:"
    nl: 	 	.asciiz 	"\n\n"
    print_txt:	.asciiz		"\nPRINT..:\n"
    

    Von Zeile 9-20 ist der Code der für die Eingabe erfordelich ist.
    Die Zeilen 45-61 sind die Zeilen, die die Zahlen in der Console ausgeben.
    Die Zahlen werden im Stack gespeichert (weiss nicht ob das, das beste ist???).
    Die Zeilen 22-43 sind die Zeilen die dem folgenden Code entsprechen sollen..:

    int i,temp;
       while(elemente--)
          for(i = 1; i <= elemente; i++)
             if(array[i-1] > array[i]) {
                temp=array[i];
                array[i]=array[i-1];
                array[i-1]=temp;
             }
    

    ...allerdings, und hier ist mein Problem, kann ich

    while(elemente--)
    

    nicht umsetzen, und das ist mein eigentliches Problem, also habe ich bis jetzt nur die for-Schleife umgesetzt..!
    Das heisst, wenn ich das Programm ausführe und z.B. 9, 3, 1, 0 eingebe, also die Zahlen 9,3 und 1 - dann sortiert er die NICHT richtig, ich bekomme das Ergebnis 3 - 1 - 9, anstatt das gesuchte 1-3-9.
    Das passiert so, weil die while-schleife nicht ausgeführt wird.(da ich das nicht umsetzen kann).

    Hoffe ihr versteht mein Problem, bin für jede Antwort offen, auch wenn ihr mir nen anderen Assembler-Code als meinen anbietet. (Bin sicher, das mein Code nicht der beste für diese Prob. ist, da ich ja anfänger bin..!)

    Danke schon im voraus für euere Antworten..!



  • was genau ist das problem dabei? du kannst es der einfachheit halber ein wenig zerlegen

    also statt

    while(elemente--)
    {
    }
    

    dann

    int Tmp=elemente;
    elemente=elemente-1;
    if(Tmp!=0)
    {
      do
      {
    
        Tmp=elemente;
        elemente=elemente-1;
      }while(Tmp!=0)
    }
    

    btw. bist du dir sicher dass das korrekter mips assembler code ist? ich sehe da nirgens etwas was darauf hindeutet, dass du dir des branch delay slots bewust bist. oder ist der simulator ne spezielle abart von mips?



  • Erstmal thx für deine Antwort..!
    Ja, ich bin mir sicher, dass das korrekter MIPS Assembler Code ist (Also Code für den MIPS-Simulator).
    Dass jetzt der Code richtig ist bin ich mir nicht sicher, auf jeden Fall funktioniert er so (benutze PCSpim 6.5), natürlich ohne den while-Befehl, da ich das noch nicht geschafft habe zu implentieren.

    Ich versuche dir mal mein Gedanken, die zu diesem Code geführt haben zu erleutern, vielleicht verstehst du dann mein Problem.
    Ich suchte eine Möglichkeit die vom User eingegebene Zahlen zu speichern, also habe ich mir überlegt das so zu machen:

    sw $s1, ($sp)        # speichere die zahl im stack
    addi $sp,$sp,-4      # zeiger(stack-pointer) zeigt eine stelle weiter im stack
    

    Die erste Zahl wird im Stack gespeichert, der Stack-Pointer um ein Wort erhöht, damit ich ja die nächste Zahl speichern kann. Das passiert in eine schleife, bis der User die 0 getippt hat...wenn das passiert versuche ich die Zahlen zu sortieren (das ist der nächste Schritt).
    Damit ich weiss wieviele Zahlen der User eingetippt hat, erhöhe ich den register $s0, der am Anfang 0 ist, bei jeder Eingabe immer um 1.

    addi $s0,$s0,1        # $s0 um 1 erhöhen, da der user eine eingabe gemacht hat
    

    Wenn jetzt der User die 0 getippt hat gehe ich mittels

    beq  $s1,0, sort    # wenn die zahl gleich 0 ist --> gehe zu sort
    

    zu dem zweiten Schritt, der Sort heisst.
    Weil jetzt der Stack-pointer auf der letzten Zahl zeigt multipliziere ich $s0 (also die Anzahl der Zahlen, dei der User getippt hat) mit der 4 mit folgendem Befehl

    mul $t0,$s0,4        # $t0 = $s0 * 4 - Anzahl der Elemente mal 4
    

    und addiere das ergebnis mittels

    add $sp,$sp,$t0
    

    mit dem Zeiger, so das jetzt der Stack-pointer wieder am Anfang zeigt(also auf der ersten eingegebenen Zahl)
    Diese Zahl speichere ich in $t1, erhöhe den Zeiger um ein Wort weiter, sodas er auf die zweite zahl zeigt, speichere die nachfolgende Zahl in $t2, vergleiche ob die Zahlen verschieden sind und wenn $t2 < $t1, dann vertausche ich die Zahlen und speichere die wieder im Stack (Zeile 36-43).
    Hier erhöhe ich noch den register $s2 (ist am anfang 0) um eins. (Den brauche ich um die sort_loop schleife zu verlassen)
    Dann vergleiche ich die nächsten beiden Zahlen usw usw. Das ganze passiert so oft bis $s2 = $s0 ist..:

    beq $s2,$s0,print    # wenn $s2 gleich $s0, dann gehe zu print
    

    Wenn das passiert sollte eigentlich die sort_loop nochmal laufen und zwar so oft wie die Anzahl der eingegebene Zahlen, also so oft wie $s0.

    Der Zeiger sollte eigentlich an der letzten Zahl zeigen und ich sollte dann mit dem Befehl

    mul $t0,$s0,4        # $t0 = $s0 * 4 - Anzahl der Elemente mal 4
        add $sp,$sp,$t0
    

    den Zeiger wieder auf der ersten Zahl zeigen lassen.

    Leider passiert das ja nicht, weil wie du bei print siehst muss ich erst

    mul $t0,$s0,4        # $t0 = $s0 * 4 - Anzahl der Elemente mal 4
        add $sp,$sp,$t0  # NORMAL
    

    und dann

    addi $sp,$sp,-4     # NICHT NORMAL
    

    also den Zeiger noch eine Stelle weiter zeigen lassen.
    Ich glaube hier liegt mein Problem.

    Sonst könnte ich while so schreiben

    while:
          beq $s4,$s0,print # wenn $s4=$s0, dann wurde while n mal ausgeführt
                            # also gehe zu print (n: Anzahl der Zahlen)
          addi $s2,$s2,$zero # $s2=0, damit die sort_loop schleife wieder n mal läuft
          addi $s4,$s4,1     # $s4 += 1
          j sort_loop
    
    sort_loop:
          # alles bleibt gleich, nur der befehl "beq $s2,$s0,print" ändert sich in
          beq $s2,$s0, while # da ich ja die while-schleife wiederholen will
    

    Hoffe du hast mein Problem verstanden..!
    MFG Bonafide..!


Log in to reply