Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Return
Forum - C/C++ - Return - Pagina 2

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Godrek (Normal User)
Pro


Messaggi: 76
Iscritto: 04/08/2015

Segnala al moderatore
Postato alle 12:01
Giovedì, 19/01/2017
Ok tutto chiaro.
Scusatemi ma per ora sto studiando semplicemente il linguaggio C e non il linguaggio macchina, quindi non ho grandi conoscenze del basso livello.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6405
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 12:07
Giovedì, 19/01/2017
Comunque è un fatto intuitivo ...

Puoi pensare che ritorni al chiamante restituendo un valore.


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
GN (Member)
Guru


Messaggi: 772
Iscritto: 30/04/2011

Segnala al moderatore
Postato alle 12:10
Giovedì, 19/01/2017
Comunque @Nessuno secondo me la domanda un senso ce l'ha, anche se non vedo che rilevanza possa avere nella programmazione ad alto livello in C.
Se per "ritornare un valore" intendiamo "scriverlo nel registro corretto" e per "terminare la funzione" si intende "liberare lo spazio occupato sullo stack delle chiamate", allora, volendo, su una RISC in cui lo stack è gestito manualmente (conosco solo la MIPS, per questo continuo a tirare fuori quella), nello scrivere codice assembly, se all'inizio della funzione ho allocato spazio sullo stack per delle variabili locali, alla fine della funzione stessa posso anche prima far decrescere lo stack (facendo una add sullo stack pointer) e poi spostare il valore di ritorno, che magari ho in un altro registro, nel registro in cui il chiamante se lo aspetta secondo le convenzioni.

Per questo dicevo che dipende dall'architettura e da come il compilatore genera l'assembly.

Tutto dipende dal significato che diamo alle parole, se per "terminare la funzione" si intendeva "fare il jump al chiamante" (che in effetti è il significato più ovvio) allora sono d'accordo che a rigor di logica deve per forza essere quella l'ultima istruzione del chiamato.

Ultima modifica effettuata da GN il 19/01/2017 alle 16:40
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6405
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 12:31
Giovedì, 19/01/2017
Testo quotato

Postato originariamente da GN:

Comunque @Nessuno secondo me la domanda un senso c'e l'ha



No, mi dispiace ma la domanda un senso non "ce l'ha".

Testo quotato

Per questo dicevo che dipende dall'architettura e da come il compilatore genera l'assembly.



Ma che c'entra? Questo avviene in ogni architettura. Ma non ha a che fare con la domanda.

NON c'è un prima e un dopo.

Puoi inserire il valore in eax (o qualunque registro deputato alla restituzione del valore), in seguito fare mille operazioni (senza modificare il valore di eax) e alla fine la ret. Oppure inserire il valore in eax e poi subito la ret. Ma il discorso non cambia.
Non è che scrivendo il valore in eax "hai restituito nulla", semplicemente "prepari il valore da restituire" che è diverso.
Quando esegui la ret e termini la funzione, il chiamante può esaminare il valore di eax per usare il valore restituito.
Parlare di "prima" o "dopo" non ha senso.

Testo quotato

l'ultima istruzione del chiamato.



L'ultima istruzione della funzione è la ret (comunque si chiami per la CPU) che riporta l'esecuzione al chiamante.


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Godrek (Normal User)
Pro


Messaggi: 76
Iscritto: 04/08/2015

Segnala al moderatore
Postato alle 13:19
Giovedì, 19/01/2017
Quello che intendevo io per "ritornare il valore" era scrivere il valore nel registro corretto mentre per "terminare la funzione" intendevo "liberare lo spazio relativo alla funzione sullo stack e fare il jump alla funzione chiamante nella riga di codice immediatamente successiva alla chiamata.
Interpretata così quindi, l'ordine è il seguente?
1. ritornare il valore
2. terminare la funzione

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6405
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 13:35
Giovedì, 19/01/2017
Testo quotato

Postato originariamente da Godrek:

Quello che intendevo io per "ritornare il valore" era scrivere il valore nel registro corretto mentre per "terminare la funzione" intendevo "liberare lo spazio relativo alla funzione sullo stack e fare il jump alla funzione chiamante nella riga di codice immediatamente successiva alla chiamata.
Interpretata così quindi, l'ordine è il seguente?
1. ritornare il valore
2. terminare la funzione



L'errore sta nell'intendere "ritornare il valore" come "scrivere il valore nel registro". Non è così, anche se capisco l'equivoco.

Quindi non dire prima ritorna e poi termina perché è un "non sense".

Ultima modifica effettuata da nessuno il 19/01/2017 alle 13:36


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Template (Member)
Pro


Messaggi: 177
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 19:47
Giovedì, 19/01/2017
Testo quotato

Postato originariamente da nessuno:

L'errore sta nell'intendere "ritornare il valore" come "scrivere il valore nel registro". Non è così, anche se capisco l'equivoco.




Purtroppo questa assurdità è avallata dalle traduzioni in italiano di moltissimi testi di programmazione (quelli della famigerata banda Deitel anzitutto)... una delle tante cose abominevoli delle edizioni italiane di testi che sarebbe meglio studiare in lingua inglese.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6405
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 20:34
Giovedì, 19/01/2017
Per chiarire un po' ...

Supponi di avere questa riga nel main

int v = somma(v1, v2);

che chiama una semplice funzione somma passando due argomenti e che riceve da questa la somma degli argomenti.
Una funzione del genere potrebbe essere questa

int somma(int a, int b)
{
    return a+b;
}

A questo punto, il compilatore traduce la chiamata nel main così
        
00161039 8B 55 FC             mov         edx,dword ptr [v2]  
0016103C 52                   push        edx  
0016103D 8B 45 F8             mov         eax,dword ptr [v1]  
00161040 50                   push        eax  
00161041 E8 BA FF FF FF       call        somma (0161000h)  
00161046 83 C4 08             add         esp,8  
00161049 89 45 F4             mov         dword ptr [v],eax  

passando nello stack, in ordine inverso, gli argomenti.
La funzione viene chiamata dalla call e quando l'esecuzione termina, nel main viene
corretto il puntatore dello stack e copiato eax in memoria all'indirizzo della variabile v
(solo perché nel main il valore restituito dalla funzione viene utilizzato in seguito).

La funzione somma sarà tradotta così

00161000 55                   push        ebp  
00161001 8B EC                mov         ebp,esp  
00161003 8B 45 08             mov         eax,dword ptr [ a ]  
00161006 03 45 0C             add         eax,dword ptr [ b ]  
00161009 5D                   pop         ebp  
0016100A C3                   ret  

in cui viene preparato il registro ebp per accedere agli argomenti nello stack e si esegue
l'addizione tra loro con risultato in eax (PROPRIO perché la somma da restituire deve stare in eax, dove se l'aspetta il main)
A questo punto, prima di terminare con la ret, viene ripristinato il vecchio valore di ebp, e solo dopo la ret permette di
continuare l'esecuzione del programma dopo la call.

A questo punto è evidente che non ha senso parlare di "ritorno del valore" prima o dopo il "termine della funzione".
Bisogna solo conoscere bene il semplice meccanismo di esecuzione del codice e passaggio dei dati.

Ultima modifica effettuata da nessuno il 19/01/2017 alle 20:52


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo