Homepage  Il progetto dsy.it è l'unofficial support site dei corsi di laurea del Dipartimento di Scienze dell'Informazione e del Dipartimento di Informatica e Comunicazione della Statale di Milano. E' un servizio degli studenti per gli studenti, curato in modo no-profit da un gruppo di essi. I nostri servizi comprendono aree di discussione per ogni Corso di Laurea, un'area download per lo scambio file, una raccolta di link e un motore di ricerca, il supporto agli studenti lavoratori, il forum hosting per Professori e studenti, i blog, e molto altro...
In questa sezione è indicizzato in textonly il contenuto del nostro forum


.dsy:it. .dsy:it. Archive > Didattica > Corsi A - F > Architettura degli elaboratori e delle reti
 
[HELP on MIPS] lettura e comparazione stringhe
Clicca QUI per vedere il messaggio nel forum
lallyblue
Ciao a tutti!
sto facendo un programmino in assembler x il MIPS e voglio chiedere all'utente se vuole ricominciare o terminare.
Mi aspetto un carattere:
se scrive 'y' ricomincio
se scrive 'n' mi fermo
se scrive altro glielo richiedo.

Riesco a leggere l'input ma poi non riesco a fare il confronto con i caratteri 'y' e 'n' per fare i relativi salti.

Qcuno mi aiuta?

Questo e' il codice che ho scritto relativamente a questo problema:

nella sezione .data:
code:
repeat: .asciiz "\nWant to do it again?\n" answer: .asciiz "" yes: .ascii "y" no: .ascii "n"

nella sezione .text:
code:
# chiede se ricominciare (main) o finire (exit) final: # stampa stringa di richiesta ripetizione programma la $a0, repeat li $v0, 4 syscall j again again: # legge risposta da input la $a0, answer # sara' solo y o n, non null terminated li $a1, 2 # quindi 1 solo byte e' sufficiente li $v0, 8 syscall # controlla la risposta la $t2, yes la $t3, no beq $a0, $t2, main # se la risposta e' y, allora ripeti da (main) beq $a0, $t3, exit # se la risposta e' n, allora esci dal programma (exit) j again # se la risposta e' altro, richiedi (again) # esce dal programma exit: li $v0, 10 syscall

e nel main:
code:
main: # Start of code section # svuoto i registri temporanei li $t0, 0 li $t2, 0 li $t3, 0


ah, nei commenti potrebbe esserci qualche imprecisione sul 'non terminated' o meno, perche' sto facendo un po' di prove...

kingoff
può dipendere dal fatto che qundo l'utente digita "y" o "n" in realtà viene memorizzato "y/0" e n"/0" (ora nn ricordo se era slash o backslash...)...perchè se nn ricordo male .asciiz mette automaticamente il carattere di terminazione alla fine, .ascii normale no......quindi quando confronti la risposta con yes e no confronti ad esempio yes(= "y") con "y/0" quindi è false
E' solo un 'idea......probabilmente sbaglio...al max prova, se ho ragione tanto meglio!

lallyblue
ci ho provato, ma non trovo la combinazione giusta...
mi interesserebbe capire la teoria a monte per non tirare a caso, ma qcosa di sintetico e chiaro...
non trovo nemmeno esempi di codice che trattino stringhe/caratteri... :(
l'altra idea, oltre al carattere terminatore, potrebbe essere che passo indirizzo anziche' valore o viceversa, ma anche qui non mi e' troppo chiaro come lavori...

lallyblue
alla fine, con grande pazienza del mio moroso, siamo riusciti a sistemare il codice... :)
in definitiva bisogna usare lb quando si vuol leggere un solo carattere e lasciare una dimensione di 3 quando leggo in input.
posto il codice completo corretto e funzionante (magari non e' ottimale ma puo' servire da spunto... ;) ):
code:
# FATTORIALE .globl main .data # Data declaration section inputstr: .asciiz "\nInserire un numero:\n" error: .asciiz "\nErrore: inserire un numero positivo.\n" outputstr: .asciiz "\nRisultato: " repeat: .asciiz "\n\nWant to do it again?\n" ansbuffer: .space 3 yes: .byte 0x79 # =y no: .byte 0x6e # =n .text # legge un intero e lo mette in $v0 e ritorna al codice chiamante leggiint: li $v0, 5 syscall jr $ra # stampa un intero da $a0 e ritorna al codice chiamante stampaint: li $v0, 1 syscall jr $ra # stampa una stringa da $a0 e ritorna al codice chiamante stampastr: li $v0, 4 syscall jr $ra # chiede se ricominciare (main) o finire (exit) final: # stampa stringa di richiesta ripetizione programma la $a0, repeat li $v0, 4 syscall # j again #again: # legge risposta da input la $a0, ansbuffer # sara' solo y o n, non null terminated li $a1, 3 # quindi 1 solo byte e' sufficiente li $v0, 8 syscall # controlla la risposta lb $t0, ansbuffer lb $t1, yes lb $t2, no beq $t0, $t1, main # se la risposta e' y, allora ripeti da (main) beq $t0, $t2, exit # se la risposta e' n, allora esci dal programma (exit) j final # se la risposta e' altro, richiedi (again) # esce dal programma exit: li $v0, 10 syscall # controlla se $t0 e' minore/uguale/maggiore di zero e salta alla relativa label check: bltz $t0, inputneg beqz $t0, inputzero bgtz $t0, inputpos # arriva qui dalla check # se il numero passato in input e' NEGATIVO # stampa un messaggio d'errore e richiede i dati in input inputneg: la $a0, error jal stampastr j asknum # arriva qui dalla check # se il numero passato in input e' ZERO # il risultato (1) e' gia' in $t1 quindi chiama la procedura che lo stampa ed esce inputzero: la $a0, outputstr jal stampastr j printres # arriva qui dalla check # se il numero passato in input e' POSITIVO # calcola ricorsivamente il risultato # mette il risultato in $t1 e chiama la procedura che lo stampa ed esce inputpos: # moltiplico il numero attuale ($t0) con il risultato parziale ($t1) # lo metto in $t1 come nuovo risultato parziale mulou $t1, $t0, $t1 # decremento il numero attuale ($t0) addi $t0, $t0, -1 # chiamata ricorsiva alla check j check # stampa il risultato dal registro $t1 ed esce printres: move $a0, $t1 li $v0, 1 jal stampaint j final main: # Start of code section # svuoto i registri temporanei li $t0, 0 li $t1, 0 li $t2, 0 # chiede il numero in input e lo memorizza in $t0 asknum: la $a0, inputstr jal stampastr jal leggiint move $t0, $v0 # inizia il calcolo del fattoriale del numero calculate: # inizializza $t1 a 1 li $t1, 1 # controlla se il numero e' minore/uguale/maggiore di zero # la check poi a seconda del valore manda alla procedura corretta da eseguire j check # END OF PROGRAM

fabioang
Forse ti puo' aiutare :D:D:D:D:D. Ciao

.data

szNewNumber: .asciiz "Vuoi continuare (s/S/y/Y) ? "
szYesChars: .asciiz "sSyY"

.text

main:

MainLoop:

la $a0, szNewNumber # chiedo all'utente se vuole calcolare un altro numero
la $a1, szYesChars
jal ReadYes

beq $v0, 1, MainLoop # continuo il programma se la funzione ReadYes ha restituito 1


##################################################
###########################
#
# int ReadYes(const char* promptMessage, const char* yesChars)
#
# Descrizione:
# Legge un carattere da tastiera verificando che sia uguale a uno dei
# caratteri referenziati dal registro $a1
#
# Registri utilizzati:
# $a0 = indirizzo della stringa da stampare
# $a1 = indirizzo della stringa di caratteri accettati come risposta positiva
# $v0 = valore di ritorno, $v0 = 1 se il carattere inserito e' uguale a uno
# dei caratteri della stringa referenziata da $a1 altrimenti $v0 = 0
#
##################################################
###########################

ReadYes:
addi $sp, $sp, -16 # alloco spazio nello stack (4 words * 4 bytes ciascuna = 12)
sw $ra, 0($sp) # memorizzo l'indirizzo di ritorno $ra nello stack
sw $a0, 4($sp) # memorizzo il registro $a0 nello stack
sw $a1, 8($sp) # memorizzo il registro $a1 nello stack
sw $zero, 12($sp) # azzero i 4 byte che utilizzo come buffer temporaneo

li $v0, 4 # stampo la stringa puntata da $a0
lw $a0, 4($sp) # recupero il valore di $a0 dallo stack
syscall

li $v0, 8 # leggo una stringa e la memorizzo in un buffer allocato nello stack
addi $a0, $sp, 12 # il buffer si trova nel record di attivazione a partire da $sp+12
li $a1, 2 # dimensione del buffer compreso lo zero finale (leggo solo un carattere)
syscall

li $v0, 4 # stampo un carriage return
la $a0, szCharCR
syscall

lb $t0, 12($sp) # leggo il primo byte del buffer e lo memorizzo in $t0

lw $t1, 8($sp) # recupero il valore di $a1 dallo stack e lo memorizzo in $t1
ReadYes_loop:
lbu $t2, 0($t1) # memorizzo in $t2 il primo byte referenziato da $t1 (stringa caratteri accettati)
bnez $t2, ReadYes_c1 # se il valore e' diverso da zero (fine stringa) continuo la funzione
li $v0, 0 # altrimenti termino la funzione restituendo 0
j ReadYes_ret
ReadYes_c1:
bne $t2, $t0, ReadYes_c2 # se il valore e' diverso da $t0 continuo la funzione
li $v0, 1 # altrimenti termino la funzione restituendo 1
j ReadYes_ret
ReadYes_c2:
addi $t1, $t1,1 # incremento $t1, il puntatore alla stringa di caratteri accettati
j ReadYes_loop

ReadYes_ret:

lw $a1, 8($sp) # ripristino il registro $a1
lw $a0, 4($sp) # ripristino il registro $a0
lw $ra, 0($sp) # ripristino il registro $ra
addi $sp, $sp, 16 # ripristino il valore iniziale dello stack pointer
jr $ra

Powered by: vbHome (lite) v4.1 and vBulletin v2.3.1 - Copyright ©2000 - 2002, Jelsoft Enterprises Limited
Mantained by dsy crew (email) | Collabora con noi | Segnalaci un bug | Archive | Regolamento |Licenze | Thanks | Syndacate