[MIPS Assembly] Problema a trovare elementi dispari del vettore

gabriele86

Utente Attivo
13
0
CPU
Intel quadcore q9300 2,5ghz
Scheda Madre
asus pq5
HDD
500Gb
RAM
Corsair Dominator 2Gb 1066mhz
GPU
Ati 3860 hd
Monitor
Agneovo 17 pollici
PSU
520
Case
Chackra con monsterfan
OS
xp ed ubuntu
Ciao a tutti mi hanno chiesto di controllare questo codice in assembly mips

Codice:
             .data
etc2:        .asciiz     "Il risultato è: "
st1:         .asciiz     "Benvenuto \nProgetto Assembly 2010"
st4:        .asciiz        "\nProgramma Terminato"
errore:        .asciiz        "\nNon è dispari"

vettore:     .word       1,2,3,4,5,6,7,8,9,10,-1         # vettore di numeri pari e dispari interi positivi

             .text
            .globl __start

__start:       li $v0, 4                        #messaggio di benvenuto
               la $a0, st1
               syscall

               la $a0,vettore                    #caria l'indirizzo del vettore nel registro $a0

               lw $s1,0($a0)                    #carica la prima posizione dell'array nel registro $s1        

confronto:       add $a0, $a0 4                    #aumenta il contatore per il vettore di una posizione
               bgez  $s1,numerodispari    #se il registro contiene è maggiore o uguale a 0 vai a vedere se è dispari 
               j media                            #se i valori li hai ispezionati tutti vai a fare la media                

numerodispari: li   $t3, 2                         #carica nel registro $t3 il numero 2
               div     $s1, $t3                    #dividi il numero per 2
               mfhi $t2                            #Hi = HI contiene il resto e lo porto nel registro $t2  
               beq $t2, 0,nondispari             #se il resto è uguale a 0 allora il numero non è dispari e vai a nondispari
               jal  aggiungi                    #altrimenti aggiungi il numero per poi fare la media da eseguire

aggiungi:       add  $s5 $s5, $s1                #aggiungi il numero trovato nel registro contenitore $s5
               add  $s7 $s7, 1                    #creo un contatore a parte per il numero di elementi dispari inseriti ( $s7 )
               add  $s6 $s6, 1                    ####contatore che aumenta in base al numero di elementi analizzati ( FITTIZIO SOLO DI CONTROLLO)
               jal  confronto                    #salta all'etichetta confronto

nondispari:       
                li $v0, 4                        #messaggio per il risultato
               la $a0, errore
               syscall
                
               move $a0, $t4                    #stampa il risultato
               li $v0, 1
               syscall                    #salta all'etichetta confronto

media:           div $s5, $s7                        #quando tutto il vettore è stato scansionato fai la media 
               mfhi $t4                            #degli elementi dispari presenti e metti il risultato in $t4
               jal risultato                    # ora che hai fatto la media vai a mostrare il risultato

risultato:       li $v0, 4                        #messaggio per il risultato
               la $a0, etc2
               syscall
                
               move $a0, $t4                    #stampa il risultato
               li $v0, 1
               syscall
               j uscita                         #salta all'uscita del programma

uscita:           li $v0, 4                        #messaggio di uscita
               la $a0, st4
               syscall
               
               li $v0,10                        #codice di uscita 
               syscall

Praticamente lo scopo è quello di trovare quali elementi del vettore siano dispari sommarli tra di loro e ritornare la media, premetto che non avendo scritto io il codice ci possono essere errori nel uso dei registri ( cosa che verrà sistemata in un secondo momento ) il programma così com è entra in un loop continuo è nella console da come risultati

Pari: 25
Dispari: 30
Benvenuto
Progetto Assembly 2010
 

Mr Storm

Utente Attivo
77
19
CPU
Intel Core i5 750
Scheda Madre
Asus P7P55D Deluxe
HDD
500 GB
RAM
Corsair 8GB DDR3 1600 MHz
GPU
Sapphire HD5850
Monitor
Asus VK222H 22"
PSU
OCZ ModXstream Pro 700W
OS
Windows 7 Professional x64
Ho dato un'occhiata al codice... l'idea c'è, ma l'implementazione lascia decisamente a desiderare :D

L'errore che causava il loop è dato dal fatto che viene letto solo il primo elemento del vettore e non uno ad ogni ciclo: infatti la lw corrispondente si trova prima della label "confronto".
Inoltre ritengo improprio l'utilizzo della jal, che dovrebbe essere usata per la chiamata di funzione, visto che salva automaticamente l'indirizzo di ritorno nel registro $ra: poiché non sono presenti procedure nel codice ma semplici label, meglio usare la semplice j, che risulta più veloce, visto che non deve salvare tale valore.
Consiglio inoltre di inizializzare sempre i registri contenitore o contatore a zero, poiché non mi sembra che i registri siano tutti azzerati di default all'avvio del programma.
Un'altra ottimizzazione consiste nell'inizializzare a 2 il registro $t3 una sola volta all'inizio del programma, e non ad ogni ciclo come nel codice postato, visto che questo non viene mai modificato.
Inoltre sono presenti un sacco di istruzioni branch / jump inutili, come quello prima della label "aggiungi" oppure i due salti prima della label "numerodispari" che possono essere ridotti a uno.
Piccolo errore di distrazione, il risultato della divisione tra $s5 e $s7 va preso dal registro $Lo, non da $Hi.
Inoltre ci sono altri piccoli errori di sintassi: mancanza di virgole, etc etc.

Insomma, un esempio di codice funzionante è il seguente:
Codice:
.data

etc2:	.asciiz		"Il risultato e: "
st1:	.asciiz		"Benvenuto \nProgetto Assembly 2010"
st4:	.asciiz		"\nProgramma Terminato"

vettore:	.word	1,2,3,4,5,6,7,8,9,10,-1		# vettore di numeri pari e dispari interi positivi

.text

# Registro -> Utilita
# $t3 -> contiene il valore 2
# $s5 -> somme parziali dei dispari del vettore
# $s7 -> contatore dei numeri dispari
# $s1 -> contiene l'elemento che sara' analizzato

.globl main

main:			li $v0, 4					# messaggio di benvenuto
				la $a0, st1
				syscall
				
				li $t3, 2
				li $s5, 0					# inizializza a zero il registro contenitore
				li $s7, 0					# inizializza a zero il contatore dei dispari

				la $a0, vettore				# carica l indirizzo del vettore nel registro $a0			

confronto:		lw $s1, 0($a0)				# carica un elemento dell array nel registro $s1        
				add $a0, $a0, 4				# aumenta il contatore per il vettore di una posizione
				bltz $s1, media				# se il registro contiene e maggiore o uguale a 0 vai a vedere se e dispari        
				
				div $s1, $t3               	# dividi il numero per 2
				mfhi $t2                    # Hi = HI contiene il resto e lo porto nel registro $t2  
				beq $t2, 0, confronto      	# se il resto e uguale a 0 allora ignora il numero

aggiungi:		add  $s5, $s5, $s1           # aggiungi il numero trovato nel registro contenitore $s5
				addi $s7, $s7, 1            # creo un contatore a parte per il numero di elementi dispari inseriti ( $s7 )
				j confronto              	# salta all etichetta confronto


media:			div $s5, $s7                # quando tutto il vettore e stato scansionato fai la media 
				mflo $t4                    # degli elementi dispari presenti e metti il risultato in $t4

stampa:			li $v0, 4                   # messaggio per il risultato
				la $a0, etc2
				syscall
				
				move $a0, $t4               # stampa il risultato
				li $v0, 1
				syscall

				li $v0, 4                   # messaggio di uscita
				la $a0, st4
				syscall
               
				li $v0, 10                    # codice di uscita 
				syscall

Si tratta di un codice non del tutto robusto in quanto, se il vettore contiene tutti numeri pari, viene eseguita una divisione per zero presso la div sulla label "media": basta un controllo sul contatore $s7, comunque, per scongiurare il pericolo :)
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!