Funzione Somma RiscV

di Vincenzo.79 il
12 risposte

Salve a tutti; ho bisogno di un aiuto nel programma che, come da titolo, deve stampare la somma di una serie di interi inseriti dall'utente...

Il programma effettua la somma con i diversi valori inseriti dall'utente...sembra funzionare. 

Il mio dubbio è nella funzione somma, alla fine del codice.

A cosa servirebbe l'uso di "sw" ed "lw"? 

Il programma funzione ugualmente anche senza di loro; se invece li abilito, s0 restituisce sempre zero e a quel punto non avrei la somma...

Grazie in anticipo a chi mi riesce a darmi una mano

.data
	title:			.asciz "\n *** SOMMA DI PIU' NUMERI ***"
	in_num:		.asciz "\n Quanti numeri vuoi inserire: "
	num:		.asciz " Inserisci un valore: "
	sum:			.asciz "\n La somma dei numeri inseriti è: "
	msg_error:	.asciz "\n Il numero inserito non è corretto, riprova! "
.text
.globl _main
_main:
la a0, title
li a7, 4
ecall
# Inserimento dei numeri da sommare
restart:
	la a0, in_num
	li a7, 4
	ecall
	li a7, 5
	ecall
	mv t1, a0

	bgtz t1, start		# Controllo per costringere all'utente di inserire un numero positivo
						# in caso contrario il programma visualizza un messaggio di errore
						# e chiede nuovamente di inserire un numero

	la a0, msg_error	# Massaggio di errore
	li a7, 4
	ecall
	j restart			# Torna all'inizio per richiedere un nuovo numero
start:
	li t0, 0			# Inizializzo il contatore (i = 0)
	li s0, 0			# Inizalizzo la somma t0 = 0
loop:
	bge t0, t1, fine	# Ciclo per far inserire una serie di valori decisi dall'utente
	la a0, num
	li a7, 4
	ecall
	li a7, 5
	ecall
	jal ra, func_sum	# Utilizzo della funzione somma
	addi t0, t0, 1
	j loop

fine:
# Stampa della somma
	la a0, sum		
	li a7, 4
	ecall
	mv a0, s0
	li a7, 1
	ecall
	
li a7, 10
ecall

# La funzione somma
func_sum:
	addi sp, sp, -8
# 	sw s0, 0(sp)		# CODICE NON CHIARO
	add s0, s0, a0
#	lw s0, 0(sp)		# CODICE NON CHIARO
	addi sp, sp, 8
	ret

12 Risposte

  • Ho individuato il problema che sta prevalentemente nella funzione;

    Il mio obiettivo è quello di effettuare la somma dei numeri inseriti dall'utente...

    in questa sezione di codice, prima di tutto uso un solo registro quindi correggo la dimensione dello stack a 4; detto ciò, ora il problema l'ho rilevato sulla parte di sw ed lw...se li tolgo il programma funzione, se li inserisco ovviamente s0 viene nuovamente portato a 0 e quindi la somma non viene aggiornata...

    Ho provato anche a salvare il valore di s0 in un altro registro...ma a questo punto a cosa servirebbe poi usare più registri se poi comunque li devo resettare prima di uscire dalla funzione?

    # La funzione somma
    func_sum:
    	addi sp, sp, -4
    # 	sw s0, 0(sp)		# CODICE NON CHIARO
    	add s0, s0, a0
    #	lw s0, 0(sp)		# CODICE NON CHIARO
    	addi sp, sp, 4
    	ret
  • Credo di esserne venuto a capo...ho semplicemente invertito i comandi tra sw ed lw...

    a questo punto, cambia la richiesta...per chi ha un pò di tempo, può cortesemente dare una sguardo al codice se è fatto bene (nonostante funzioni)?

    Grazie

    .globl _main
    
    .data
    	title:				.asciz "\n *** SOMMA DI PIU' NUMERI ***"
    	in_num:				.asciz "\n Quanti numeri vuoi inserire: "
    	num:				.asciz " Inserisci un valore: "
    	sum:				.asciz "\n La somma dei numeri inseriti è: "
    	msg_error:			.asciz "\n Il numero inserito non è corretto, riprova! "
    
    .text
    _main:
    la a0, title
    li a7, 4
    ecall
    # Inserimento dei numeri da sommare
    restart:
    	la a0, in_num
    	li a7, 4
    	ecall
    	li a7, 5
    	ecall
    	mv t1, a0
    
    	bgtz t1, start		# Controllo per costringere all'utente di inserire un numero positivo
    						# in caso contrario il programma visualizza un messaggio di errore
    						# e chiede nuovamente di inserire un numero
    
    	la a0, msg_error	# Massaggio di errore
    	li a7, 4
    	ecall
    	j restart			# Torna all'inizio per richiedere un nuovo numero
    start:
    	li t0, 0			# Inizializzo il contatore (i = 0)
    	li s0, 0			# Inizalizzo la somma t0 = 0
    loop:
    	bge t0, t1, fine	# Ciclo per far inserire una serie di valori decisi dall'utente
    	la a0, num
    	li a7, 4
    	ecall
    	li a7, 5
    	ecall
    	jal ra, func_sum	# Utilizzo della funzione somma
    	mv a1, s0
    	addi t0, t0, 1
    	j loop
    
    fine:
    # Stampa della somma
    	la a0, sum		
    	li a7, 4
    	ecall
    	mv a0, a1
    	li a7, 1
    	ecall
    # Fine del programma	
    li a7, 10
    ecall
    
    # La funzione somma
    func_sum:
    	addi sp, sp, -4
     	lw s0, 0(sp)
    	add s0, s0, a0
    	sw s0, 0(sp)	
    	addi sp, sp, 4
    	ret
    
  • 09/07/2026 - Vincenzo.79 ha scritto:

    # La funzione somma 

    func_sum:
    	addi sp, sp, -4
     	lw s0, 0(sp)
    	add s0, s0, a0
    	sw s0, 0(sp)	
    	addi sp, sp, 4
    	ret

    perchè tutti quei comandi per una somma?

    riesci a spiegare cosa stai facendo?

    pierino spende 1 euro per 3 mele, 2 euro per 5 banane, quanto ha speso?

    fai semplicemente

    risultato=risultato + nuovo_valore

    quindi

    inizializzi risultato=0

    la funzione fa questo

    risultato=0+1=1

    poi fa 

    risultato=1+2=3

    func_sum:
      add s0, s0, a0   # s0 = s0 (memorizzato) + a0 (numero inserito)
      ret
  • Volevo usare lo stack, forse (anzi sicuramente) l'ho fatto erroneamente...

    perchè avrei dovuto usare prima la funzione di store word e poi load word, ma in questo caso il valore contenuto nello stack si resetta a zero e la funzione non restituisce il valore somma che poi è quello che deve fare...

    Se il blocco di codice dalla funzione lo rifaccio in questo modo, ovviamente la funzione non torna la somma...e mi stampa sempre 0

    func_sum:
    	addi sp, sp, -4
     	sw s0, 0(sp)
     	
     	add s0, s0, a0
    		
    	lw s0, 0(sp)
    
    	addi sp, sp, 4
    	ret
  • 10/07/2026 - sihsandrea ha scritto:

    10/07/2026 - Vincenzo.79 ha scritto:

    addi sp, sp, -4

    Toglilo!

    Se tolgo solo la riga di codice che mi hai indicato, la somma viene aggiornata soltanto sull'ultimo numero inserito...quindi non funzione. Ho provato togliendo anche 

    addi sp, sp, 4

    In questo modo funziona, ma non uso poi lo stack...

    In effetti il codice della funzione diventa, ma a questo punto mi chiedo, a cosa serve sw ed lw:

    # La funzione somma
    func_sum:
    #	addi sp, sp, -4		# TOLTO
     	lw s0, 0(sp)
    	add s0, s0, a0
    	sw s0, 0(sp)	
    #	addi sp, sp, 4		# TOLTO
    	ret
  • 10/07/2026 - Vincenzo.79 ha scritto:

    Volevo usare lo stack, forse (anzi sicuramente) l'ho fatto erroneamente..

    func_sum:
       addi sp, sp, -4   STAI RISERVANDO 4 BYTE SULLO STACK CHE NON CONTIENE NULLA
       lw   s0, 0(sp)    STAI LEGGENDO LO STACK CHE NON CONTIENE NULLA
       add  s0, s0, a0   STAI SOMMANDO IL NULLA
       sw   s0, 0(sp)    STAI MEMORIZZANDO IL NULLA
       addi sp, sp, 4    TORNI DOVE AVEVI IL VALORE DA SOMMARE
       ret

    E LO FAI OGNI VOLTA CHE USI LA FUNZIONE SOMMA.
    SE DEVI USARE LO STACK ALLORA:
       - DEVI INSERIRE NELLO STACK IL VALORE DI SP
       - DEVI FARLO SOLO UNA VOLTA NEL MAIN NON NEL CALCOLO

    QUINDI NEL MAIN:
       addi sp,sp,-4   CREI LO STACK
       sw ra,0(sp)
       
       ....            QUI NEL CICLO CHIAMI LA FUNZIONE

       lw ra,0(sp)
       addi sp,sp,4    TORNI NELLA POSIZIONE ORIGINARIA

    LA FUNZIONE DEVE SOLO FARE LA SOMMA

    func_sum:
       lw   t0, 0(sp)
       add  t0, t0, a0
       sw   t0, 0(sp)
       ret

  • Grazie mille...tutto un pò più chiaro.

    Allora vediamo un pò se ho capito bene: in effetti devo usare lo stack quando ho funzioni che richiamano altre funzioni, altrimenti non ha senso usare lo sp; in questo programma non servirebbe usare lo sp...corretto?

    Un chiarimento finale: nella funzione somma ho usato un registro temporaneo t2...va bene o avrei dovuto usarne uno tipo s0???

    Dove potrei prendere qualche esercizio per rinforzare l'utilizzo dello stack?

    Posto il codice completo con le correzioni:

    # Programma che effettua la somma di una serie di numeri inseriti dall'utente.
    # La funzione somma è stata sviluppata con lo stack
    
    .globl _main
    
    .data
    	title:				.asciz "\n *** SOMMA DI PIU' NUMERI ***"
    	in_num:		.asciz "\n Quanti numeri vuoi inserire: "
    	num:			.asciz " Inserisci un valore: "
    	sum:				.asciz "\n La somma dei numeri inseriti è: "
    	msg_error:	.asciz "\n Il numero inserito non è corretto, riprova! "
    
    .text
    _main:
    # Creazione dello stack
    addi sp, sp, -4
    sw ra, 0(sp)				# Salvo il registro ra (indirizzo di ritorno) nella memoria
    
    la a0, title
    li a7, 4
    ecall
    # Inserimento dei numeri da sommare
    restart:
    	la a0, in_num
    	li a7, 4
    	ecall
    	li a7, 5
    	ecall
    	mv t1, a0
    
    	bgtz t1, start		# Controllo per costringere all'utente di inserire un numero positivo
    								# in caso contrario il programma visualizza un messaggio di errore
    								# e chiede nuovamente di inserire un numero
    
    	la a0, msg_error	# Massaggio di errore
    	li a7, 4
    	ecall
    	j restart				# Torna all'inizio per richiedere un nuovo numero
    start:
    	li t0, 0					# Inizializzo il contatore (i = 0)
    
    loop:
    	bge t0, t1, fine		# Ciclo per far inserire una serie di valori decisi dall'utente
    	la a0, num
    	li a7, 4
    	ecall
    	li a7, 5
    	ecall
    	jal ra, func_sum	# Utilizzo della funzione somma
    	addi t0, t0, 1
    	j loop
    
    fine:
    # Stampa della somma
    	la a0, sum		
    	li a7, 4
    	ecall
    	mv a0, t2
    	li a7, 1
    	ecall
    
    # Torno nella posizione originaria
    lw ra, 0(sp)					# Carico il valore di sp dalla memoria al registro di ritorno ra
    addi sp, sp,4
    
    # Fine del programma	
    li a7, 10
    ecall
    
    # La funzione somma
    func_sum:
    	lw t2, 0(sp)				# Carica il dato dalla memoria e lo salvo nel registro ra.
    	add t2, t2, a0			# Calcolo della somma dei numeri inseriti
    	sw t2, 0(sp)				# Salvo il registro t2 (che poi è il valore della somma) nella memoria 0(sp)
    	ret
  • Per fare pratica con lo stack su architettura RISC-V e capire come funziona a livello di registri, puntatori e chiamate a funzione, puoi usare le seguenti risorse:

    • Simulatori Visuali: Usa Ripes (il più consigliato per la didattica) o Venus per scrivere assembly, posizionare breakpoint ed eseguire il codice step-by-step vedendo lo stack che cresce o si riduce. [1]
    • Esercizi Universitari Strutturati: Puoi seguire le esercitazioni del corso CS61C dell'UC Berkeley, che contengono problemi pratici sulla gestione delle procedure e stack frame in RISC-V. Trovi materiali ed esercizi nel sito del corso CASS. [1]
    • Esercizi di Base (Istruzioni di Prologo/Epilogo): Esercitati ad allocare spazio nello stack (addi sp, sp, -x) e deallocarlo (addi sp, sp, x). Scrivi funzioni in assembly che salvano e ripristinano i registri salvati (s0-s11) e l'indirizzo di ritorno (ra). [1, 2]
    • Sfide Avanzate (Funzioni Ricorsive): La ricorsione è l'esercizio perfetto per lo stack. Esercizi classici includono la sequenza di Fibonacci o il calcolo del Fattoriale. [1, 2, 3]
    • Reverse Engineering e Sicurezza: Per spingerti oltre, puoi simulare i problemi di Stack Buffer Overflow allocando buffer troppo piccoli e osservando con il debugger come i dati sovrascrivono l'indirizzo di ritorno sullo stack.
  • 11/07/2026 - sihsandrea ha scritto:

    Per fare pratica con lo stack su architettura RISC-V e capire come funziona a livello di registri, puntatori e chiamate a funzione, puoi usare le seguenti risorse:

    • Simulatori Visuali: Usa Ripes (il più consigliato per la didattica) o Venus per scrivere assembly, posizionare breakpoint ed eseguire il codice step-by-step vedendo lo stack che cresce o si riduce. [1]
    • Esercizi Universitari Strutturati: Puoi seguire le esercitazioni del corso CS61C dell'UC Berkeley, che contengono problemi pratici sulla gestione delle procedure e stack frame in RISC-V. Trovi materiali ed esercizi nel sito del corso CASS. [1]
    • Esercizi di Base (Istruzioni di Prologo/Epilogo): Esercitati ad allocare spazio nello stack (addi sp, sp, -x) e deallocarlo (addi sp, sp, x). Scrivi funzioni in assembly che salvano e ripristinano i registri salvati (s0-s11) e l'indirizzo di ritorno (ra). [1, 2]
    • Sfide Avanzate (Funzioni Ricorsive): La ricorsione è l'esercizio perfetto per lo stack. Esercizi classici includono la sequenza di Fibonacci o il calcolo del Fattoriale. [1, 2, 3]
    • Reverse Engineering e Sicurezza: Per spingerti oltre, puoi simulare i problemi di Stack Buffer Overflow allocando buffer troppo piccoli e osservando con il debugger come i dati sovrascrivono l'indirizzo di ritorno sullo stack.

    Grazie infinite...

Devi accedere o registrarti per scrivere nel forum
12 risposte