Grazie.. sono andato avanti con il progetto !
l'unico problema è che quando voglio tornare alla scelta, mi da un errore
es: - cancello,i dispari ok
- richiedo quale azione si vuole eseguire
- la scelta mi da un errore e non mi fa andare avanti
eccoti il programma:
#Es_1
.data
asterischi: .asciiz "*******************************************\n"
menu1: .asciiz "** Gestione lista di stringhe **\n"
menu2: .asciiz "** Scegliere una tra le seguenti opzioni **\n"
spazio: .asciiz " "
uno: .asciiz "** 1. Crea lista **\n"
due: .asciiz "** 2. Elimina dispari **\n"
tre: .asciiz "** 3. Elimina pari **\n"
quattro: .asciiz "** 5. Esci **\n"
inserire: .asciiz "\n Inserire l'intero corrispondete alla scelta: "
insert: .asciiz "\n Inserire l'intero: "
elem: .asciiz "\n Elementi inseriti:"
nil: .asciiz "\n Nil\n\n"
canc: .asciiz "\nInserire la stringa da cancellare/inserire: "
arrivederci: .asciiz "\nArrivederci!!!"
ri_inserisci: .asciiz "\n ERRORE!!! L'intero scelto non rientra nel range possibile.\n"
aggiunta: .asciiz "\n essendo la catena non vuota aggiungi nuovi elementi: \n"
.align 2
jump_table: .space 16 #ho bisogno di 20 byte per allocare 4 indirizzi, ognuno di 4 byte
.text
.globl main
#prima procedura richiesta che si occupa della creazione della lista di stringhe
create:
bne $t8,$zero,aggiungi
move $t8 $zero # s0 (= Testa) = 0
move $t9 $zero # s1 (= Coda ) = 0
bne $t8, $zero, inputloop
li $v0, 4
la $a0, nil
syscall
inputloop: # inizio loop di input;
li $v0, 4
la $a0, insert
syscall # stampa messaggio
li $v0, 5
syscall
beq $v0, $zero, print # se l'intero letto e' zero, salta all'etichetta print (stampa)
move $t1, $v0 # altrimenti t1=input
# inizio inserzione nuovo elemento
li $v0, 9
li $a0, 8 #8 byte, 1 per l'intero e uno per il puntatore.
syscall # chiamata sbrk: restituisce un blocco di 8 byte, puntato da v0: il nuovo record
# vegono riempiti i due campi del nuovo record:
sw $t1, 0($v0) # campo intero = t1
sw $zero, 4($v0) # campo elemento-successivo = nil
bne $t8, $zero, link_last # se s0!=nil (coda non vuota) vai a link_last
move $t8, $v0 # altrimenti (prima inserzione) Testa=Coda=v0
move $t9, $v0
j inputloop # torna all'inizio del loop di input
link_last: # se la coda e' non vuota, collega l'ultimo elemento della lista,
# puntato da Coda (s1) al nuovo record; dopodiche' modifica Coda
# per farlo puntare al nuovo record
sw $v0, 4($t9) # il campo elemento successivo dell'ultimo del record prende v0
move $t9, $v0 # Coda = v0
j inputloop
print: beq $t8,$zero,stampaN # loop di stampa di tutti gli elementi della coda, separati da spazi
move $t0, $t8 # t0 = Testa. t0 verra' usato come puntatore per scorrere gli elementi della lista
li $v0, 4
la $a0, elem
syscall
loop_print:
beq $t0, $zero, uscita # se t0 == 0 si e' raggiunta la fine della lista e si esce
li $v0, 1 # altrimenti si stampa l'elemento corrente. Cioe':
lw $a0, 0($t0) # a0 = valore del campo intero dell'elemento corrente (puntato da t0)
syscall # stampa valore intero dell'elemento corrente
li $v0, 4
la $a0, spazio
syscall # stampa spazio
lw $t0, 4($t0) # t0 = valore del campo elemento-successivo dell'elemento corrente (puntato da t0)
j loop_print # salta all'inizio del ciclo di stampa
uscita:
move $v0, $t8
move $v1, $t9
jr $ra
aggiungi:
j inputloop
sw $a0, 4($t9) #carico nell'area puntatore dell'ultimo record l'indirizzo del nuovo record che diventa la nuova coda
move $v1, $a0 #passo il nuovo valore della coda tramite $v1, la coda precedente non è più corretta. Il valore lo copio subito per poter fare la stampa
li $v0, 4
la $a0, aggiunta
syscall
move $v0, $t8 #passo il valore della testa tramite $v0
jr $ra #torno al chiamante
# Eliminazione numeri dispari
delete_d:
li $s4,2
move $t0,$a0
move $t6,$a1
move $t7,$a0
beq $t0, $zero, vuota
trova:
lw $s0, 0($t0)
div $s0, $s4
mfhi $s3
bnez $s3, elimina_d
beq $t0,$t6,esci
move $t1, $t0 #punto il record attuale, mentre $t0 si sposta, nel caso in cui debba fare una cancellazione
lw $t0, 4($t0)
move $t3,$t0
bne $t1,$t6, trova
move $v0,$t7
move $v1,$t6
jr $ra
elimina_d:
beq $t0, $t7, cambio_testa_d #se il record contenente la stringa da cancellare è il primo devo solo riallocare il puntatore alla testa
beq $t3, $t6, cambio_coda_d #controllo se il record da eliminare è la coda, così cambio il puntatore
lw $t3, 4($t0)
lw $t2, 4($t0) #altrimenti carico l'indirizzo del record successivo in $t2 (che uso come appoggio)
sw $t2, 4($t1) #e questo indirizzo lo salvo nell'apposita area del record precedente puntato da $t1
lw $t0, 4($t0)
move $v0, $t7 #restituisco il valore della testa, memorizzato in partenza in $t7, tramite $v0
move $v1, $t6 #restituisco il valore della coda tramite $v1
bne $t0,$t6, trova
jr $ra
cambio_testa_d:
lw $t7, 4($t0) #carico in $t7 l'indirizzo del successivo record che diventa così la testa della catena
move $t0,$t7
move $v0,$t7 # lo salvo in v0 per restituirlo al chiamante
beqz $v0, azzera_coda_d #se la testa appena eliminata era l'unico elemento della catena adesso $v0 vale zero, e lo stesso deve succedere per la coda
move $v1, $t6 #altrimenti restituisco anche il valore della coda copiandolo da $t6
j trova
azzera_coda_d: #si eseguono queste istruzioni se la testa eliminata era anche l'unicoelemento della catena
move $v1, $zero
jr $ra
cambio_coda_d:
move $v0, $t7
move $v1, $t1
jr $ra
vuota:
move $v1,$zero
jr $ra
esci:
jr $ra
# Eliminazione numeri pari
delete_p:
li $s4,2
move $t0,$a0
move $t6,$a1
move $t7,$a0
beq $t0, $zero, vuota_p
trova_p:
lw $s0, 0($t0)
div $s0, $s4
mfhi $s3
beq $s3, $zero, elimina_p
beq $t0,$t6,esci_p
move $t1, $t0 #punto il record attuale, mentre $t0 si sposta, nel caso in cui debba fare una cancellazione
lw $t0, 4($t0)
bne $t1,$t6, trova_p
move $v0,$t7
move $v1,$t6
jr $ra
elimina_p:
beq $t0, $t7, cambio_testa_p #se il record contenente la stringa da cancellare è il primo devo solo riallocare il puntatore alla testa
beq $t0, $t6, cambio_coda_p #controllo se il record da eliminare è la coda, così cambio il puntatore
lw $t2, 4($t0) #altrimenti carico l'indirizzo del record successivo in $t2 (che uso come appoggio)
sw $t2, 4($t1) #e questo indirizzo lo salvo nell'apposita area del record precedente puntato da $t1
lw $t0, 4($t0)
move $v0, $t7 #restituisco il valore della testa, memorizzato in partenza in $t7, tramite $v0
move $v1, $t6 #restituisco il valore della coda tramite $v1
bne $t0,$t6, trova_p
jr $ra
cambio_testa_p:
lw $t7, 4($t0) #carico in $t7 l'indirizzo del successivo record che diventa così la testa della catena
move $t0,$t7
move $v0,$t7 # lo salvo in v0 per restituirlo al chiamante
beqz $v0, azzera_coda_p #se la testa appena eliminata era l'unico elemento della catena adesso $v0 vale zero, e lo stesso deve succedere per la coda
move $v1, $t6 #altrimenti restituisco anche il valore della coda copiandolo da $t6
j trova_p
azzera_coda_p: #si eseguono queste istruzioni se la testa eliminata era anche l'unicoelemento della catena
move $v1, $zero
jr $ra
cambio_coda_p:
move $v0, $t7
move $v1, $t1
jr $ra
vuota_p:
move $v1,$zero
jr $ra
esci_p:
jr $ra
############################################## procedura main
main:
#istanziamento jump table
la $s0, jump_table #memorizzo l'indirizzo della jump_table in $s0
la $t0, j_uno #carico l'indirizzo delle scelte nella tabella tramite una "sw"
sw $t0, 0($s0) #con un offset di 4 byte, perchè ogni indirizzo è di 32 bit
la $t0, j_due
sw $t0, 4($s0)
la $t0, j_tre
sw $t0, 8($s0)
la $t0, j_quattro
sw $t0, 12($s0)
menu:
#serie di istruzioni per stampare il menù
li $v0, 4
la $a0, asterischi
syscall
li $v0, 4
la $a0, menu1
syscall
li $v0, 4
la $a0, menu2
syscall
li $v0, 4
la $a0, spazio
syscall
li $v0, 4
la $a0, uno
syscall
li $v0, 4
la $a0, due
syscall
li $v0, 4
la $a0, tre
syscall
li $v0, 4
la $a0, quattro
syscall
li $v0, 4
la $a0, asterischi
syscall
choose:
li $v0, 4
la $a0, inserire
syscall
#leggo l'intero scelto dall'utente
li $v0, 5
syscall
bgt $v0, 4, ri_ins #Branch if greater than: se l'intero inserito è maggiore di 5 allora si chiede all'utente di inserire un intero corretto
#tornando alla label "choose" dopo aver stampato un messaggio d'errore
blt $v0, 1, ri_ins #la stessa considerazione vale se l'intero inserito è minore di 1
sub $v0, $v0, 1 #per calcolare l'offset da sommare all'indirizzo a partire dal quale è memorizzata la jump_table si sottrae 1 alla scelta
mul $v0, $v0, 4 #perchè la prima case_action corrisponde ad un offset uguale a zero, e si moltiplica per quattro
add $v0, $s0, $v0 #l'offset così ottenuto si somma all'indirizzo della jump_table ottendo l'indirizzo da cui prelevare a sua volta l'indirizzo
lw $v0, 0($v0) #della case action opportuna tramite questa "lw"
jr $v0 #salto all'indirizzo memorizzato in $v0
ri_ins:
li $v0, 4
la $a0, ri_inserisci
syscall
j choose
j_uno:
jal create
move $s1, $v0 #$s1==testa
move $s2, $v1 #$s2==coda
j choose
j_due:
move $a0, $s1 #passo l'indirizzo della testa tramite $a0
move $a1,$s2
jal delete_d
move $s1, $v0 #$s1==testa
move $s2, $v1 #$s2==coda
beqz $v1, stampaNil
j stampa_stringa
stampaNil:
li $v0, 4
la $a0, nil
syscall
j choose
j_tre:
move $a0, $s1 #passo l'indirizzo della testa tramite $a0
move $a1, $s2 #passo l'indirizzo della coda tramite $a1
jal delete_p
move $s1, $v0 #$s1==testa
move $s2, $v1 #$s2==coda
beqz $v1, stampaN
j stampa_stringa
stampaN:
li $v0, 4
la $a0, nil
syscall
j choose
stampa_stringa:
# loop di stampa di tutti gli elementi della coda, separati da spazi
move $s4, $s1 # t0 = Testa. t0 verra' usato come puntatore per scorrere gli elementi della lista
li $v0, 4
la $a0, elem
syscall
loop:
# se t0 == 0 si e' raggiunta la fine della lista e si esce
li $v0, 1 # altrimenti si stampa l'elemento corrente. Cioe':
lw $a0, 0($s4) # a0 = valore del campo intero dell'elemento corrente (puntato da t0)
syscall # stampa valore intero dell'elemento corrente
beq $s4, $s2,choose
li $v0, 4
la $a0, spazio
syscall # stampa spazio
lw $s4, 4($s4) # t0 = valore del campo elemento-successivo dell'elemento corrente (puntato da t0)
j loop
j_quattro:
li $v0, 4
la $a0, arrivederci
syscall
#termine dell'esecuzione
li $v0, 10
syscall