Correzione e verifica programma in Assembler Mips

di il
6 risposte

Correzione e verifica programma in Assembler Mips

Ciao a tutti, sto imparando il linguaggio assembler Mips e ho voluto cimentarmi con un esercizio. Calcola la somma degli elementi in un array. Ho scritto prima il codice C e poi volevo tradurlo in assembler Mips (senza il main, solo le procedure). Suppongo che l'array sia già da qualche parte e anche la sua dimensione. Vi posto il codice:

Codice C = http://pastebin.com/x2z6MQ1

Immagino che:

A: .word {7,3,1,4,5} # Questo è il mio Array A di 5 elementi.
$a0 # Registro che contiene la dimensione di A.
$a1 # Registro che punta all'indirizzo base del vettore A.
$v0 # Registro che conterrà il risultato della somma.
Queste sono le procedure:

somma: add $t3 , $a1 , $zero      # t3 punta allo stesso indirizzo di memoria di a1. 
             add $t1 , $zero , $zero  #  t1 = 0 ( la variabile "i" nel codice C).
         
loop: slt $t2 , $t1 , $a0      # if (i < n) t2 = 1, else t2 = 0.
        bne $t2 , 1 , EXIT    # if (t2 è diverso da 1) vai all'etichetta EXIT.
        lw $t4 , 0($t3)         # Carico nel registro t4 il primo elemento di A cioè 5.
        add $v0 , $v0 , $t4 # v0 = 0 + 5.
        sll $t3 , $t3 , 2       # t3 punta all'indirizzo di mememoria successivo (2° elemento di A).
        addi $t1 , $t1 , 1   # i = i + 1
        j loop

EXIT: Qui devo printare il risultato?   
Ho scritto in t3 lo stesso indirizzo di a1 perchè ho pensato che per scorrere il vettore bastava solamente cambiare l'offset , dell'istruzione lw $t4 , 0($t3) , di 4 in 4 . Ma visto che nel loop non posso cambiarlo di volta in volta, allora cambio il registro base (lo faccio puntare all'elemento in questione), così che l'offset rimanga sempre 0.

C'è qualcosa di sbagliato? Funziona?

Grazie delle eventuali risposte.

6 Risposte

  • Re: Correzione e verifica programma in Assembler Mips

    Ciao
    allora dove hai messo la condizione che $t2 deve essere <=$a0 per uscire dal ciclo?
    $t2 non deve essere <> da 1 perchè ?
    ti scrivo un codice di esempio su come si gestiscono gli array cosi che tu lo possa modificare.
    l'esempio non fà niente altro che azzerare un vettore
    move $t0,$zero 
    ciclo: add $t1,$t0,$t0
    add $t1,$t1,$t1
    add $t2,$a0,$t1
    sw $zero,0($t2)
    addi $t0,$t0,1
    slt $t3,$t0,$a1
    bne $t3,$zero,ciclo

    volutamente non ci ho messo il commento al fine di farti comprendere meglio.
    se qualche punto non ti è chiaro fammelo sapere cosi te lo spiego.
  • Re: Correzione e verifica programma in Assembler Mips

    Anzitutto grazie per la risposta.
    allora dove hai messo la condizione che $t2 deve essere <=$a0 per uscire dal ciclo?
    La condizione dovrebbe essere questa:
    
    slt $t2 , $t1 , $a0      # if (i < n) t2 = 1, else t2 = 0
    
    Infatti così dico: se i (t1) è < di n (a0) allora t2 = 1, mentre appena i > n allora t2 = 0. Quindi sto ricalcando l'uscita del ciclo for fatto in C.
    $t2 non deve essere <> da 1 perchè ?
    se ti rifesrici a questa linea di codice:
    
    bne $t2 , 1 , EXIT
    
    L'ho messa perchè dall'esecuzione di slt $t2 , $t1 , $a0 in t2 avrò o 1 o 0. Quindi se t2 è diverso da 1 allora vuol dire che i (t1) > n (a0) e quindi salto all'uscita (EXIT). In pratica il clico for in C è concluso. Altrimenti (se i (t1) < n (a0) ) continua ad eseguire il ciclo per sommare gli elementi.

    Grazie del codice, la cose che non mi è chiara è cos'è $a0 e $a1. Intendi $a0 come puntatore al primo elemento del vettore e $a1 la dimensione del vettore?

    Grazie ancora!
  • Re: Correzione e verifica programma in Assembler Mips

    Ciao
    allora per il mio esempio
    $a0 = al indirizzo del array
    $a1 = alla dimensione dell'array

    comunque in assembly mips i for si implementano come se fossero dei repeat until
    cosi come hai fatto tu si implementano i while.
    la repeat until
    prima esegue le operazioni e poi effettua la condizione.
    la differenza con il for e che le istruzioni vengono eseguite almeno una volta mentre con il for si rischia che il blocco non venga eseguito.

    ti posto il link con le syscall mips cosi puoi aggiungere anche la fase di visualizzazione.
    http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html

    riposta il programma con le modifiche che hai fatto cosi vediamo se funziona.
  • Re: Correzione e verifica programma in Assembler Mips

    Grazie mille. Quindi prima eseguo le operazioni e poi la condizione di uscita.

    E' una domanda da principiante: Ma non è uguale , in questo specifico caso, mettere la condizione di uscita prima che vengano eseguite le operazioni? Ho impostato precedentemente la i a zero, quindi non dovrebbe dare problemi.

    Parlando in generale la tua osservazione mi convince. E' buona regola seguirla sempre. Però volevo sapere se anche così il programma funzionerebbe.

    Codice assembler modificato:
    
    somma: add $t3 , $a1 , $zero      # t3 punta allo stesso indirizzo di memoria di a1.
                 add $t1 , $zero , $zero  #  t1 = 0 ( la variabile "i" nel codice C).
             
    loop: 
            lw $t4 , 0($t3)         # Carico nel registro t4 il primo elemento di A cioè 5.
            add $v0 , $v0 , $t4 # v0 = 0 + 5.
            sll $t3 , $t3 , 2       # t3 punta all'indirizzo di mememoria successivo (2° elemento di A).
            addi $t1 , $t1 , 1   # i = i + 1
            slt $t2 , $t1 , $a0      # if (i < n) t2 = 1, else t2 = 0.
            bne $t2 , 1 , EXIT    # if (t2 è diverso da 1) vai all'etichetta EXIT.
            j loop
    
    EXIT: 
              li $v0 , 1                         # Numero che identifica il print.
              add $a0 , $v0 , $zero  # Carico in a0 il valore che sta in v0.
             syscall
    
    Il mio valore finale sta nel registro v0, è corretto?
  • Re: Correzione e verifica programma in Assembler Mips

    Allora se parliamo di teoria
    non c'è nessun problema a mettere il confronto prima di fare le operazioni.
    ma se le mettiamo prima dobbiamo essere consci che il blocco potrebbe non essere mai eseguito e che implementiamo una struttura rispetto ad un altra.
    sappi che ci sono casi in cui è obbligatorio mettere prima i confronti e poi il codice e casi in cui è obbligatorio il contrario.
    tornando alla pratica
    il tuo programma eseguito da un operatore umano puo funzionare
    ma non ti darebbe il risultato sperato
    perchè il registro v0 serve per la chiamata alla syscall e se tu lo usi anche come output avrai come risultato il valore di chiamata della sys.
    siccome però non sono gli umani a eseguire i programmi ma i computer il tuo programma non funziona ancora.
    perchè manca:
    definizione dei segmenti
    l'entry point alias il main
    e l'end point alias la chiamata alla syscall che chiude il programma.
    un programma eseguito da computer in assembler mips
    necessita delle seguenti sessioni:
    .data
            # definizione del segmento dati se è necessario. 
            # nel tuo caso lo è
    .text  # segmento del codice (obbligatoria)
    .globl xxxx #definizione dei simboli globbali alias definisce una routine o un programma xxx è il nome della routine.
    label di partenza (questa l'hai messa!
    .......... #codice del programma che deve essere eseguito
    ..........
    .......... 
    li $v0, 10 #chiamata alla syscall di uscita che libera tutte le risorse allocate.
         syscall
    da questo sito ti puoi scaricare, gratuitamente, il compilatore qtspim
    http://spimsimulator.sourceforge.net
    una volta che avrai compilato il programma se vuoi possiamo discutere su:
    1) eventuali errori di compilazione
    2) mal funzionamenti vari
    3) renderlo più performante
  • Re: Correzione e verifica programma in Assembler Mips

    Grazie mille dei chiarimenti. Per adesso sono soddisfatto.
    Grazie dei link che hai postato!
Devi accedere o registrarti per scrivere nel forum
6 risposte