2013-07-07 10 views
12

Ho letto che quando una chiamata di funzione viene effettuata da un programma, la funzione chiamata deve sapere come tornare al suo chiamante.Come richiamare le funzioni richiamate al chiamante, dopo essere stati chiamati?

La mia domanda è: in che modo la funzione chiamata sa come tornare al proprio chiamante? C'è un meccanismo che lavora dietro le quinte attraverso il compilatore?

+1

Si dovrebbe leggere [this] (http://en.wikipedia.org/wiki/Call_stack#Structure) Questa è una risposta molto buona: [Capitolo 11 - Procedure] (http: //pages.cs.wisc. edu/~ smoler/x86text/lect.notes/procedures.html) E se ti piace Video: [Assembly Primer for Hackers (Part 11) Functions Stack] (http://www.progamercity.net/code-tut/168- assembly-language-primer-hackers-video-series.html) ti piaceranno tutti i video qui. –

risposta

12

Il compilatore obbedisce a una particolare "convenzione di chiamata", definita come parte dell'ABI a cui si sta indirizzando. Tale convenzione di chiamata includerà un modo per il sistema di sapere a quale indirizzo tornare. La convenzione di chiamata di solito sfrutta il supporto dell'hardware per le chiamate di procedura. Su Intel, per esempio, l'indirizzo di ritorno viene inserito nello stack:

... processore spinge il valore di EIP registro (che contiene l'offset della successiva all'istruzione CALL) in pila (da utilizzare successivamente come puntatore di ritorno).

ritorno da una funzione avviene tramite l'istruzione ret:

... processore schiocca il puntatore all'istruzione ritorno (offset) dalla sommità della pila nel registro EIP e comincia esecuzione del programma sul nuovo puntatore di istruzioni.

Per contrastare, su ARM, l'indirizzo di ritorno viene messo nel registro delle link:

Il BL e BLX istruzioni copiare l'indirizzo della successiva istruzione in lr (r14, il registro dei collegamenti).

I ritorni vengono comunemente eseguiti eseguendo movs pc, lr per copiare l'indirizzo dal registro di collegamento nuovamente nel registro del contatore di programma.

Riferimenti:

  1. Intel Software Developers Manual
  2. ARM Information Center
4

Ciò è reso possibile dallo stack (soprattutto sui sistemi Intel-like). Diciamo che abbiamo un metodo caller che include, per esempio, uno int che mantiene localmente.

Quando caller( chiama target( che int deve essere salvato. Viene messo in pila, insieme all'indirizzo da cui è stata effettuata la chiamata. target( può eseguire la sua logica, creare le proprie variabili locali e chiamare altri metodi. Le sue variabili locali saranno posizionate sullo stack insieme all'indirizzo della chiamata.

Quando target( termina, lo stack è "srotolato".La parte superiore della pila contenente le variabili locali di target( viene rimossa.

Quando i metodi vengono inoltrati troppo lontano, la pila potrebbe diventare troppo grande e potrebbe verificarsi uno "overflow dello stack".

8
  1. Il compilatore sa come chiamare una funzione e quale convenzione di chiamata viene utilizzata. Ad esempio in C gli argomenti per una funzione vengono inseriti nello stack. Il chiamante è responsabile della cancellazione dello stack, quindi la funzione chiamata non deve rimuovere gli argomenti. Altre convenzioni di chiamata possono includere il push degli argomenti nello stack e la funzione chiamata deve pulirlo. In questo caso, il codice generato è tale, che la funzione corregge lo stack prima che possa tornare. Le convenzioni che chiamano Ohter possono passare gli argomenti nei registri, quindi in tal caso anche la funzione chiamata non deve fare attenzione.

  2. La CPU ha un meccanismo per chiamare una subroutine. Questo memorizzerà l'indirizzo di esecuzione corrente sullo stack e quindi trasferirà l'elaborazione al nuovo indirizzo. Quando la funzione viene eseguita, esegue un'istruzione return, che recupera l'indirizzo del chiamante e riprende l'esecuzione lì.

Se l'indirizzo di ritorno è distrutto, perché lo stack non è adeguatamente puliti uo, o la memoria viene sovrascritto, quindi si ottiene un comportamento indefinito. Naturalmente i dettagli esatti dell'implementazione variano a seconda della piattaforma utilizzata.

4

Richiede cooperazione tra il destinatario e il chiamante.

Il chiamante accetta di fornire l'indirizzo che il destinatario deve restituire al destinatario (solitamente spingendolo nello stack o passandolo in un registro) e il destinatario accetta di tornare all'indirizzo indicato al termine dell'operazione. esecuzione.

Problemi correlati