| |
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 |
[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 |
|
|
|
|