registri salvati con chiamante (noti anche come registri volatili):
* Definizione: Questi registri sono a carico del chiamante (La funzione che fa la chiamata) da preservare se i loro valori sono necessari dopo il ritorno di Callee (la funzione chiamata).
* Meccanismo: Prima di chiamare una funzione, se il chiamante ha valori importanti memorizzati nei registri salvati chiamanti, deve spingere quei valori sullo stack (o salvarli altrove in memoria). Dopo il ritorno di Callee, il chiamante può riportare i valori salvati in quei registri.
* Impatto sulle prestazioni:
* Overhead nel sito di chiamata: I registri salvati con chiamante portano al sovraccarico della funzione di chiamata. Ogni chiamata potrebbe richiedere i registri di spinta e scoppiamento, anche se il Callee non usa effettivamente quei registri.
* potenzialmente meno sovraccarico se callee è semplice: Se il Callee è piccolo e non ha bisogno di utilizzare molti registri, il chiamante potrebbe non aver bisogno di salvare nulla, rendendo la chiamata relativamente efficiente. Il chiamante salva solo i registri di cui sa di aver bisogno * e * il Callee potrebbe potenzialmente blobber.
* Adatto per valori di breve durata: Buono per le variabili che devono solo vivere attraverso un piccolo ambito, poiché il risparmio/ripristino diventa meno preoccupazione.
* Esempio: In molte convenzioni di chiamata X86-64 (come System v amd64 Abi), registri come `rax`,` rcx`, `rdi`,` rsi`, `r8`,` r9`, `r10`,` r11` (e registri flagellati come `xmm0-xmm15` su alcuni sistemi).
Registri salvati da ballee (noti anche come registri non volatili):
* Definizione: Questi registri sono a carico di Callee (la funzione che viene chiamata) da preservare. Se il Callee vuole usarli, deve salvare i loro valori originali all'inizio della funzione e ripristinarli prima di tornare.
* Meccanismo: Il Callee spinge i valori originali di questi registri sullo stack all'inizio della sua esecuzione. Prima di tornare, il Callee riporta quei valori nei registri, ripristinando efficacemente nel loro stato originale.
* Impatto sulle prestazioni:
* Overhead all'interno di Callee: I registri salvati da pallee introducono sovraccarico all'interno della funzione Callee. Ogni callee che utilizza questi registri deve eseguire risparmio e ripristino, indipendentemente da ciò che il chiamante sta facendo.
* Meglio per Callee usando molti registri: Se il Callee ha bisogno di molti registri, l'uso di registri salvati da Callee può essere più efficiente dei registri salvati con i chiamanti. Il chiamante è garantito che quei registri saranno conservati senza dover fare nulla.
* Adatto per valori di lunga durata: Buono per le variabili che devono vivere attraverso un ambito di grande funzione, poiché il sovraccarico di salvare/ripristinare viene ammortizzato per la durata più lunga del loro uso.
* Esempio: Nel sistema X86-64 contro AMD64 Abi, registri come `rbx`,` rsp`, `rbp`,` r12`, `r13`,` r14`, `r15` sono risparmiati in callee. `RSP` è speciale (puntatore dello stack) e` RBP` (puntatore di base) viene spesso utilizzato per la gestione e il debug dello stack.
Differenze chiave e implicazioni per le prestazioni:
| Caratteristica | Registri salvati con chiamante | Registri salvati Callee |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Responsabilità | Chiamante da salvare e ripristinare se necessario prima di chiamare una funzione. | Callee per salvare e ripristinare se vengono utilizzati da Callee. |
| Overhead | Principalmente nella funzione di chiamata (potenzialmente nessun sovraccarico se il chiamante non ha bisogno di quei registri). | Principalmente all'interno della funzione chiamata (sovraccarico se il chiamante ha bisogno o meno i registri conservati). |
| Miglior utilizzo | Quando il chiamante deve preservare i valori solo attraverso un piccolo sottoinsieme di chiamate. | Quando il Callee è grande e probabilmente userà molti registri, evitando che il chiamante debba salvare molti possibili registri. |
| Esempio (x86-64) | `rax`,` rcx`, `rdi`,` rsi`, `r8`,` r9`, `r10`,` r11` | `rbx`,` rsp`, `rbp`,` r12`, `r13`,` r14`, `r15` |
Qual è meglio?
Non esiste un approccio universalmente "migliore". La scelta ottimale dipende dalle specifiche delle convenzioni chiamate, dalla struttura del programma, dalla frequenza delle chiamate della funzione e dalla dimensione e dalla complessità delle funzioni. Le strategie di allocazione del registro utilizzate dai compilatori e dai programmatori mirano a ridurre al minimo il sovraccarico di salvare e ripristinare i registri scegliendo in modo intelligente quali registri da utilizzare per scopi diversi.
* Frequenti piccole chiamate: Il chiamante potrebbe essere preferibile, poiché il chiamante risparmia solo ciò di cui ha bisogno. Il Callee può utilizzare i registri senza alcun costo di risparmio/ripristino.
* Chiamate di grandi dimensioni rari: Calee salvato potrebbe essere preferibile se Callee usa molti registri. Il Callee accetterà il costo del risparmio/ripristino di quei registri, ma il chiamante viene liberato dal dover anticipare quali registri devono essere salvati.
In sintesi:
La scelta tra registri salvati con chiamante e salvati da balle comporta un compromesso tra sovraccarico nel sito di chiamata e sovraccarico all'interno della funzione chiamata. Le convenzioni efficaci di allocazione del registro e di chiamata mirano a ridurre al minimo questo sovraccarico per migliorare le prestazioni del programma. I compilatori e i programmatori di assemblaggio devono comprendere questi concetti per ottimizzare il codice per l'efficienza. L'ABI (Application Binary Interface) definisce quali registri sono salvati e quali sono salvati Calee per un'architettura e un sistema operativo specifico.
software © www.354353.com