E’ possibile sviluppare un metodo simile al comando “goto” ma più efficiente

Anche se questo comando è bistrattato un po’ da tutti, sto cercando un metodo per poterlo utilizzare in modo più efficiente.

E’ noto che in fase di compilazione ad ogni etichetta viene associato uno specifico indirizzo di memoria e lo stesso sarà poi utilizzato dal “goto” per saltare alla posizione specificata.

Ora chiedo un aiuto per trovare un metodo per leggere l’indirizzo di tali etichette e dopo averlo memorizzato, successivamente poterlo passare come parametro al comando “goto”

Un grazie anticipato.

Richiesta un po assurda :slight_smile:
1)Usare il goto è sinonimo di cattiva programmazione, nella programmazione strutturata è dimostrato
che qualunque programma si può realizzare usando le strutture di controllo, sequenza,iterazione e selezione.

  1. Il goto è l'equivalente del salto jmp presente in assembly, equivale ad un unica istruzione in linguaggio macchina, essendo le istruzioni macchina il componente più piccolo non si può modificare....

3)Anche nel linguaggio macchina "assembly", si ha un astrazione, non mi devo occupare dell'indirizzo di memoria di un salto ma uso un etichetta, senza sapere il suo indirizzo. Adesso tu in un linguaggio ad alto
livello vorresti fare quello che non si fa neanche nel linguaggio assembly.

Ti serve per forza il goto è l'indirizzo della label o ti accontenti dei puntatori a funzione, con questi hai una variabile che punta a nulla, una if che testa se punta a null e non fa nulla, ma se punta ad un indirizzo valido effettua una chiamata a funzione, ovviamente poi la funzione ritorna normalmente al chiamante e viene eseguita la prossima istruzione al punto di chiamata.

PS: le label possono essere solo locali ad una funzione, come dire non puoi saltare ad una label specificata in una diversa funzione.

Esiste poi un long jump ma solitamente si usa per il time sharing.

Ciao.

lelebum:
Ora chiedo un aiuto per trovare un metodo per leggere l’indirizzo di tali etichette e dopo averlo memorizzato, successivamente poterlo passare come parametro al comando “goto”

Mi fa pensare ad una soluzione sbagliata per un problema affrontabile in altro modo. Considerando che le etichette sono calcolate dal compilatore, mi sembra che la forma più flat per simulare un OnGoto di basica memoria sia questa:

switch (n):
{
    case 0: goto ....;
    case 1: goto ....;
    case 2: goto ....;
    case 3: goto ....;
    case 4: goto ....;
}

torn24:
Richiesta un po assurda :slight_smile:
1)Usare il goto è sinonimo di cattiva programmazione, nella programmazione strutturata è dimostrato
che qualunque programma si può realizzare usando le strutture di controllo, sequenza,iterazione e selezione.

Concordo!
A meno che non si usino (ancora) linguaggi a Programmazione Procedurale, non ha senso ed è giustamente controindicato utilizzare goto!

Federico

Maurotec:
Ti serve per forza il goto è l'indirizzo della label o ti acconti dei puntatori a funzione, con questi hai una variabile che punta a nulla, una if che testa se punta a null e non fa nulla, ma se punta ad un indirizzo valido effettua una chiamata a funzione, ovviamente poi la funzione ritorna normalmente al chiamante e viene eseguita la prossima istruzione al punto di chiamata.

umh, se ho capito bene (non ne sono sicuro), sotto sotto stai consigliando una Programmazione Strutturata! :wink:

Federico

lelebum:
Anche se questo comando è bistrattato un po’ da tutti, sto cercando un metodo per poterlo utilizzare in modo più efficiente.

Il modo più efficiente è il passaggio alla Programmazione Struttura, che altro non è che una evoluzione nell'uso dei goto. :slight_smile:

Sei proprio sicuro di non poterne fare a meno?
Non so che tipo di esperienza hai nella programmazione, ma prova a spiegarci il problema, cioè quello che vorresti fare, invece di cercare una soluzione al problema contingente (goto), forse ti si puo' consigliare una strada diversa, ma migliore, per rendere il codice pulito, più leggibile, facilmente modificabile, etc

Naturalmente sei libero di fare le scelte, ma se tutti lo sconsigliano (per tua affermazione) un motivo ci sarà :slight_smile:

Federico

Federico66:
Sei proprio sicuro di non poterne fare a meno?

Ci sono alcuni flussi di esecuzione che sono decisamente poco strutturabili, anche se la sintassi sottostante che li descrive può essere strutturata.

stati.png

Ma è facile lasciarsi "lusingare" dal goto per far coincidere flusso e sintassi :wink:

stati.png

In 'aiutateci ad aiutarvi' sta scritto:
Spiega il problema, spiegalo tutto

Claudio_FF:
Ci sono alcuni flussi di esecuzione che sono decisamente poco strutturabili, anche se la sintassi sottostante che li descrive può essere strutturata.

ok, vista cosi, non è banale, ma se ogni stato è un funzione (per rimanere nella strutturata), ogni funzione contiene delle condizioni... e, cosa più importante, sai quello che stai scrivendo e hai ben chiaro quello che vuoi ottenere non la vedo impossibile, complicato si, ma non impossibile :cold_sweat:

In ogni caso, non credo che sia il caso dell'OP, altrimenti i problemi sarebbero altri :wink:

Claudio_FF:
Ma è facile lasciarsi "lusingare" dal goto per far coincidere flusso e sintassi :wink:

appunto :slight_smile:
e non è detto che ci si riesca utilizzando il famelico goto :slight_smile:

Grazie degli interventi, ma devo chiedervi un attimo di pazienza per la dovuta replica ...

Giusto per chiarire il mio punto di vista, è da qualche anno che utilizzo Arduino ed ho scoperto la presenza del “goto” per puro caso leggendo un post che trattava tutt’altro argomento.

Ho aperto il post con il “goto” e la rispettiva etichetta per capire se era possibile manipolarla come in assembler.

Ora al fine non creare ulteriore confusione vedo di chiarire il mio progetto.

Nel corso della mia programmazione in linguaggio assembler, ho messo a punto una routine analoga al nostro bistrattato “delay()” che però non blocca la CPU.
Alla routine si passa il periodo di tempo richiesto e l’indirizzo a cui saltare al termine del conteggio ed il gioco è fatto. Utilissima nei casi dove sia richiesto una sequenza di operazioni con tempi di attuazione relativamente lunghi.

Semplice ed immediata nell’editor quanto efficiente nell’esecuzione.
Pur avendo disponibile più contatori, è sufficiente uno per realizzare una sequenza infinita di operazioni, “chiudi valvola1 -attendi – apri valvola1 – attendi – apri valvola2 - ecc.”.
Farebbe la gioia di quanti volessero creare un impianto di irrigazione senza ricorrere a complessi “millis()”

E’ da diverso tempo che tento di convertire questa routine nell’IDE di Arduino, ma il grosso scoglio è di non poter manipolare l’indirizzo.

Nel corso della mia programmazione in linguaggio assembler, ho messo a punto una routine analoga al nostro bistrattato "delay()" che però non blocca la CPU.
Alla routine si passa il periodo di tempo richiesto e l'indirizzo a cui saltare al termine del conteggio ed il gioco è fatto. Utilissima nei casi dove sia richiesto una sequenza di operazioni con tempi di attuazione relativamente lunghi.

Errore mio circa il fatto che delay blocca la CPU, poi mi sono ravveduto ed in effetti delay impegna la cpu in modo esclusivo (se escludiamo IRQ), nel tuo caso hai messo assieme la routine che impegna la cpu e l'indirizzo a cui saltare dopo avere concluso il delay.

In assembley tu spingi nello stack i due argomenti e poi fai una JMP secco, oppure mmmm... forse è meglio che posti la routine assembley così ci possiamo dare una occhiata.

Comunque il problema si presenta con la chiamata a funzione CALL che alla fine si aspetta un RET e il jump secco che in C si chiama long jump longjump
fare convivere entrambi mi sembra rischioso, se si mancano dei pop o ci sono più push che pop lo stack non è più coerente e va tutto a donnine.

Ma questo vale anche in assembley.

Pur avendo disponibile più contatori, è sufficiente uno per realizzare una sequenza infinita di operazioni, "chiudi valvola1 -attendi - apri valvola1 - attendi - apri valvola2 - ecc.".
Farebbe la gioia di quanti volessero creare un impianto di irrigazione senza ricorrere a complessi "millis()"

Si ok, ci sono soluzioni e alternative che però come sempre portano con se side effect, per il momento rimaniamo concentrati sulla routine giusto?

Ciao.

aspetta...
una routine in assembly che NON blocca la cpu, si limita ad aspettare un tempo e poi eseguire un salto....
e, mentre la CPU non è bloccata, ma sta aspettando il tempo, cosa farebbe? in quale maniera non essendo bloccata potrei utilizzarla?
scusa ma mi sembra una cosa confusa......

Claudio_FF:
Ci sono alcuni flussi di esecuzione che sono decisamente poco strutturabili, anche se la sintassi sottostante che li descrive può essere strutturata.

Ma è facile lasciarsi "lusingare" dal goto per far coincidere flusso e sintassi :wink:

io non capisco, nel tuo diagramma, come una manciata do GoTo potrebbe essere più "chiara semplice e leggibile" di una variabile di stato, uno switch case e una serie di "stato=........."
come poi un goto a indirizzi non mnemonici, ma ri-conosciuti solo dal compilatore possa essere utili, mi sfugge alla grande

lelebum:
Alla routine si passa il periodo di tempo richiesto e l’indirizzo a cui saltare al termine del conteggio ed il gioco è fatto. Utilissima nei casi dove sia richiesto una sequenza di operazioni con tempi di attuazione relativamente lunghi.

Non capisco.
Perché vuoi chiamare una routine unica ma che non ritorni alla istruzione successiva al punto di chiamata ?
Se la chiami passandogli un indirizzo a cui tornare, tanto vale chiamarla come funzione normale, poi l'esecuzione ritorna al punto successivo della chiamata e subito dopo fai il goto che "già sapevi"
Comunque, in tutti i casi, quello che vorresti fare non mi pare possibile in C puro.

P.S. non è che il goto è una istruzione poco conosciuta di Arduino. Arduino si programma in C e il C ha il goto, sconsigliato perché se si usa si rischia di avere un codice "a spaghetti" ovvero molto ingarbugliato. Ma si usa, soprattutto su piccole CPU/MCU se sei allo stretto come memoria, per risparmiare anche pochi byte di codice.
Come detto equivale ad un jmp in assembly

lelebum:
Pur avendo disponibile più contatori, è sufficiente uno per realizzare una sequenza infinita di operazioni, “chiudi valvola1 -attendi – apri valvola1 – attendi – apri valvola2 - ecc.”.
Farebbe la gioia di quanti volessero creare un impianto di irrigazione senza ricorrere a complessi “millis()”

guarda…
complessi millis() e chiari GoTo?
ci sono evidentemente dei problemi a livello di logica di programmazione, scusa se sembro brusco, ma usare un goto è “quasi” sempre sbagliato
non dico sempre, non mi viene in mente neppure un caso nel quale un goto sia necessario, neppure uno
però…
siccome K&R dicevano che potrebbe essere utile, sono disposto ad ammetterlo, per rispetto a loro, solo per quello

comunque per creare un semplice timer ciclico, basta leggere un po’, cercare, anche solo il mio “tempo delle librerie”, o mi sovviene, l’ultima volta che ho citato il tempo delle librerie qualcuno (Guglielmo, se ricordo bene) ha indicato anche un semaforo, adesso non lo ricordo, ma aveva timer ciclico e cambi di sequenza da impulsi esterni, cercalo, cercare non ti farà male…
e aggiungo, cerca anche passo a passo a spasso nel tempo…

lelebum:
Nel corso della mia programmazione in linguaggio assembler, ho messo a punto una routine analoga al nostro bistrattato “delay()” che però non blocca la CPU.
Alla routine si passa il periodo di tempo richiesto e l’indirizzo a cui saltare al termine del conteggio ed il gioco è fatto. Utilissima nei casi dove sia richiesto una sequenza di operazioni con tempi di attuazione relativamente lunghi.

Scusa, ma hai appena descritto un timer!
Dopo un tempo prestabilito eseguo una funzione.

Continuo a non capire

Federico

Questo è il codice assembler che uso per creare i miei ritardi

	call	AdslOff		; spegne modem
	ld	a,100		; tempo di ritardo 10"
	call	SoftTmr		; attivo timer e abbandono momentaneamente routine
				; la CPU continua ad eseguire il loop principale
					
;-- punto di ripresa della sub dopo il ritardo

	call	AdslOn		; riattiva modem
	ret			; uscita definitiva dalla routine

Dopo il SoftTmr la CPU è libera di eseguire il codice presente nel loop

Nella versione attuale leggo l'indirizzo di ripresa direttamente dallo stack,
mentre nella versione precedente lo passavo in modo esplicito tramite dei puntatori,
metodo più indicato per il mio progetto di conversione per Arduino.

Per i più settici posso informare che questo metodo gira interrottamente da oltre 12 anni e non ha mai creato problemi di sorta.

lelebum:
Nella versione attuale leggo l'indirizzo di ripresa direttamente dallo stack,

Ma in C lo stack NON lo gestisci tu...