2013-08-02 4 views

risposta

39

Ecco la tabella completa dei registri e il loro uso dalla documentazione [PDF Link]:

table from docs

r12, r13, r14, r15, rbx, rsp, rbp sono i registri callee-salvato - hanno avere un "Sì" nella colonna "Preservate across function calls".

+0

In aumento. Grazie mille! – boneheadgeek

+0

E per quanto riguarda le bandiere? come DF? – socketpair

+2

@socketpair: DF deve essere disattivato prima di qualsiasi chiamata o ritorno, quindi il comportamento di conteggio in alto può essere assunto senza 'cld'. I flag di condizione (come ZF) sono call-clobbered. Ho dimenticato esattamente cosa dicono i documenti ABI sulle modalità di arrotondamento FP e sui denormals-zero. Forse qualcosa come se una funzione li modifica, deve salvare/ripristinare lo stato precedente prima di tornare, ma ** non prendere la parola per la parte FP **. –

4

L'ABI specifica cosa può aspettarsi un pezzo di software conforme alle norme. È scritto principalmente per autori di compilatori, linker e altri software di elaborazione del linguaggio. Questi autori vogliono che il loro compilatore produca codice che funzioni correttamente con il codice compilato dallo stesso compilatore (o da un altro). Devono essere tutti d'accordo su un insieme di regole: in che modo gli argomenti formali alle funzioni passano dal chiamante al chiamato, come vengono restituiti i valori di ritorno delle funzioni da callee al chiamante, i cui registri sono conservati/scratch/non definiti attraverso il limite della chiamata, e così sopra.

Ad esempio, una regola indica che il codice assembly generato per una funzione deve salvare il valore di un registro conservato prima di modificare il valore e che il codice deve ripristinare il valore salvato prima di tornare al relativo chiamante. Per un registro scratch, il codice generato non è necessario per salvare e ripristinare il valore del registro; può farlo se lo desidera, ma il software conforme agli standard non può dipendere da questo comportamento (se lo fa non è un software conforme allo standard).

Se si sta scrivendo il codice assembly, è responsabile della riproduzione di queste stesse regole (si sta giocando il ruolo del compilatore). Cioè, se il tuo codice cambia un registro salvato da un callee, sei responsabile dell'inserimento di istruzioni che salvano e ripristinano il valore del registro originale. Se il codice assembly chiama una funzione esterna, il codice deve passare gli argomenti in modo conforme allo standard e può dipendere dal fatto che, quando viene restituito il chiamato, i valori di registro preservati vengono effettivamente preservati.

Le regole definiscono come il software conforme agli standard può andare d'accordo. Tuttavia, è perfettamente legale scrivere (o generare) il codice che fa non giocare con queste regole! I compilatori lo fanno sempre, perché sanno che le regole non devono essere seguite in determinate circostanze.

Ad esempio, si consideri una funzione C denominato foo che è dichiarato come segue:

static foo(int x); 

a tempo di compilazione, il compilatore è certo al 100% che questa funzione può essere richiamata solo da un altro codice nel file (s) è attualmente in fase di compilazione. La funzione foo non può essere chiamata da qualcos'altro, mai, data la definizione di cosa significa essere statici. Poiché il compilatore conosce tutti i chiamanti di foo in fase di compilazione, il compilatore è libero di utilizzare qualsiasi sequenza di chiamata che desidera (fino a non effettuare alcuna chiamata, ovvero, inserendo il codice per foo nei chiamanti di foo

Come autore del codice assembly, puoi farlo anche tu.Cioè, è possibile implementare un "accordo privato" tra due o più routine, purché tale accordo non interferisca con o violi le aspettative del software conforme agli standard.