Newsgroup: it.hobby.elettronica.digitale
Titolo: subroutine

Ciao a tutti!
che problemi potrebbero esserci se da una routine principale richiedo di 
saltare ad una subroutine (gosub) e da questa se si verificano certe eventi 
debba andare (goto)ad un'altra parte di programma? cioe' nella normalita' si 
richiede da andare ad una soubroutine questa svolto il suo compito deve 
ridare il pieno controllo alla istruzione dopo gosub se cosi' non fosse? 

E' quello che si chiama annidamento o nidificazione delle istruzioni! Ogni 
microprocessore o microcontrollore ha un numero massimo di nidificazioni. 
Praticamente ogni volta che chiami una istruzione Gosub viene salvato in un 
particolare registro la posizione di memoria successuva al gosub che hai 
richiamato in modo che quando si esegue il Return il micro sa da dove 
ripartire. Se un gosub poi richiama un altro gosub e cosě via si va incontro 
alla nidificazione e cioč vengono memorizzati nel registro (se ricordo bene 
si chiama stack pointer) con tecnica FIFO (first in first out) in modo che 
man mano che si eseguono i return si ritorna alla routine principale.
Da qui si deduce che se non si eseguono tutti i return corrispondenti ai 
propri gosub questi indirizzi non vengono cancellati dallo stack e si 
finisce per andare in stack overflow!
Spero di essere stato abbastanza chiaro
ciao


 finisce per andare in stack overflow!
Da quello che dici sembra che non sia indicato dare un goto da una routine 
che sta girando da un gosub 

 man mano che si eseguono i return si ritorna alla routine principale.
Lo stack funziona esattamente al contrario di come dici, funziona come LIFO
(last in first out), altrimenti non funzionerebbe niente.
http://it.wikipedia.org/wiki/Stack
"In informatica, il termine stack o pila viene usato in diversi contesti per
riferirsi a strutture dati le cui modalità d'accesso seguono una politica
LIFO (Last In First Out), ovvero tale per cui i dati vengono estratti
(letti) in ordine rigorosamente inverso rispetto a quello in cui sono stati
inseriti (scritti)."

 
Se calcoli bene i gosub (call) in modo che lo stack non vada in overflow
puoi farlo, ma conviene sempre ritornare nel main con lo stack vuoto
altrimenti si rischia di "perdersi"
Ad esempio se hai uno stack a 8 livelli, ti senti tranquillo a "girare" 
con 2 livelli nidificati? Possibile che non ci sia un'altra soluzione?
In un PIC con 2 livelli di stack eviterei...
( ad esempio i compilatori c su pic a 2 livelli di stack, gestiscono
le subroutine al secondo livello proprio con i goto, l'importante e 
calcolare bene i salti e fare attenzione all'interrupt eventualmente,
però 2 righe di codice C diventano un poema in assembler con tutte le 
problematiche relative)
In un ARM dove lo stack è gestito da un registro a 32bit il discorso 
cambia....
(a volte il codice assembler è piu corto del C!!! (quasi))
Quindi il punto è:
E' proprio necessario nidificare lo "stack"
 
Con che micro sto lavorando?
Che compilatore uso? (in assembler devo calcolarmi io tutto, in C ci 
pensa il compilatore, ma non sempre c'è da fidarsi....)
Emanuele
-- 
;YOUR ELECTRONICS OPEN SOURCE * 
http://dev.emcelettronica.com

 microprocessore o microcontrollore ha un numero massimo di nidificazioni.
Questo non è vero in generale, vale solo per il caso di microntrollori 
piccoli, come i PIC, gli ST6 e alcuni TinyAVR.
Nel resto del mondo lo stack è un'area della RAM e, quindi, il limite è 
variabile e assolutamente indipendente dal processore usato: tutto 
dipende da quanta RAM hai e quanta puoi dedicarne allo stack.
Inoltre nello stack ci finiscono le variabili locali (automatiche) delle 
funzioni, per cui sapere quante funzioni puoi annidare senza sfondare lo 
stack diventa molto spesso una vera e propria statistica.
Visto che si parla di sfondamento dello stack, vorrei aggiungere che 
questo problema è uno dei più comuni nel software, ed anche uno dei più 
difficili da trovare. Un programma può funzionare per mesi 
perfettamente, e crashare per stack overflow solo sotto particolari, 
sfigate, condizioni. Esistono dei sistemi per almeno rilevare questa 
condizione, ma mi sto dilungando troppo.
Ciao ciao

 In un PIC con 2 livelli di stack eviterei...
Perchè non dovrei usare tutto lo stack? Io li uso anche tutti ed 8 i 
livelli... sono fatti apposta :-)
Io a volte eseguo una call che in certi casi può anche saltare con un 
goto ad un'altra subroutine ed uscire da questa con il return e 
risparmio un livello di stack e evito di avere routine doppie o con 
picole differenze o troppo frammentate.
E' logico che si deve fare attenzione, ed io quando faccio queste 
operazioni scrivo sempre il commento accanto che mi ricorda come ho 
gestito la cosa... dopo qualche anno potrebbe essere difficile da capire.
Ciao,
Lucio

Marcus ha scritto:

Non mi sbaglio se cito le funzioni di Pop e Push!!!???
ciao
Angelo

 il compilatore, ma non sempre c'č da fidarsi....)
Sto usando come detto sopra il Basic.

Lucia ha scritto:

Esatto è proprio questo che fanno i compilatori C su micro con solo 2 
livelli di stack!
Il rischio però con 8 livelli  (e magari 2 "appesi") è quello di 
"perdersi" nel firmware, diminuire la leggibilità, etc. etc.


 
Ti hanno già risposto a tutto, inoltre viene citato anche Push e Pop
che pur non avendo le istruzioni assembler, può essere facilmente 
implementato nei pic con delle macro


"marcoangelo" <marcoangelo.r_NOSPAM_@_NOSPAM_alice.it> ha scritto nel 
messaggio news:4653080a$0$37203$4faf...@reader3.news.tin.it...

Potresti spiegarmi i particolari? non o cosa sia Pop e Push 

"Marcus" ha scritto

Se perdevi 30 secondi con google scrivendo "push" e "pop" come primo
risultato trovavi
http://www.giobe2000.it/Tutorial/Schede/06-Stack/601.asp
Da cui subito si arriva a
http://www.giobe2000.it/Tutorial/Schede/06-Stack/606.asp
Qua dovresti trovare le info che ti servono.

 ciao
Push e pop sono istruzioni assembly che servono per mettere/togliere 
dati dallo stack, ma in questo caso non credo c'entrino molto, per 2 
motivi:
1) Push e pop si usano in assembly, mentre Marcus programma in basic
2) Anche ammesso che riesca a embeddare l'assembly nel basic, e quindi 
inserire un pop manuale dello spazio dello stack occupato, essendo un 
PIC esso non dispone delle istruzioni sopracitate.
Avendo lo stack "hardware" a 8 livelli fissi, tutto viene gestito in 
automatico: viene fatto un push dell'indirizzo di ritorno al momento 
della call, ed esso viene poppato al momento del return.
Inoltre, a monte di tutto, anche se push e pop fossero disponibili, 
perchè ricorrere a trucchi così sporchi? Andare a poppare gli 
indirizzi di ritorno non mi sembra una buona idea, potrebbre causare 
bug imprevedibili e molto difficili da tracciare in un secondo tempo.
Il mio consiglio è di fare sempre le cose per bene, utilizzando 
correttamente la modularità per come è stata pensata.
Ciao

 Ciao
Grazie per il consiglio, comunque da quello che ho letto sul manuale del 
compilatore Basic che sto usando il problema non dovrei pormelo perche' il 
compilatore dovrebbe avvertirmi di una anomalia di tipo mandare lo stack in 
owerflow, inoltre se ho capito bene indica per i Pic16Fxxx un livello di 
annidamento di 4 stack  (12 per 17Cxxx e 27 per i 18Xxxx)
Riporto quanto letto:
An unlimited number of subroutines may be used in a program.
Subroutines may also be nested. In other words, it is possible for a
subroutine to call another subroutine. Such subroutine nesting must be
restricted to no more than four levels deep (12 levels for 17Cxxx and 27
levels for 18Xxxx).

 Ciao
Ciao
Angelo

 salvare nulla sullo stack!
Questo è vero, ma se hai manipolato lo stack un return non ritorna più 
dove doveva :-)
Ciao

 annidamento di 4 stack  (12 per 17Cxxx e 27 per i 18Xxxx)
Sì dovrebbe essere così, sembra che il compilatore riservi per se 4 
locazioni di stack, non so per quale motivo
Tieni comunque presente che non puoi usare funzioni ricorsive (che per 
la verità non si usano molto spesso).
Il fatto che i PIC non abbiano un vero stack è la ragione principale per 
cui non mi piacciono :-)
Ciao

 Ciao
ciao
Angelo

 Non mi sbaglio se cito le funzioni di Pop e Push!!!??? 
Che ho inteso come: "per fare quello che vuoi (tornare all'istruzione 
dopo il gosub) puoi usare push e pop in modo da liberare lo stack"
Se volevi intendere qualcos'altro ti invito a specificarlo più 
chiaramente, perchè, sinceramente, non ho capito.
Ciao