2012-05-08 15 views
8

Non capisco come dovrebbe funzionare.Perché l'assemblatore in linea GCC richiede informazioni di cancellazione, ma MSVC non è

L'assemblatore in linea GCC è un problema da correggere, ma molto specifico sulla marcatura delle informazioni sul clobbering, in modo che il compilatore sappia cosa stai facendo.

L'assembly inline di Microsoft Visual C++ è veramente facile da usare (sembra sempre Just Work), ma non ho idea di quali tipi di garanzie o supposizioni fanno sul tuo codice.

VC++ tenta di "rilevare automaticamente" quali registri sono danneggiati? Come fa a sapere come cambieranno i registri e il puntatore dello stack? Fa qualche ipotesi? Se è così, come si aggirano queste ipotesi?

risposta

19

Per quanto riguarda perché GCC non farlo nel modo MSVC fa, ci sono diverse ragioni:

  1. GCC è un compilatore retargettable, ma la sintassi assemblea è solo testo crudo. Affinché il rilevamento del clobber sia automatico, GCC dovrebbe analizzare il linguaggio assembly per capire quali registri sono stati danneggiati (compresi quelli implicitamente danneggiati da istruzioni i cui opcode non nominano un registro). Questo dovrebbe funzionare su tutte le architetture. Attualmente, GCC non analizza il linguaggio assembly; lo incolla semplicemente nell'output dell'assieme, dopo aver eseguito le sostituzioni %. L'idea è di generare ed evitare l'analisi.

  2. In linguaggio di assemblaggio in linea GCC, registri di cancellazione è l'eccezione anziché la regola. Il motivo è che è un linguaggio più sofisticato di quello in MSVC. Il linguaggio assembly inline di GCC alloca i registri per te. Quindi di solito non usi qualcosa come %eax direttamente, ma piuttosto un codice come %0 per il quale GCC sostituisce un registro disponibile. (E per fare ciò, il compilatore non deve capire il linguaggio assembly! Si esprimono i vincoli che assicurano che GCC sostituisca un registro appropriato per %0 che si adatta all'utilizzo.) È necessario solo clobber se il codice assembly è sovrascritto registri codificati, non se sovrascrive gli operandi di output assegnati per te da GCC.

Si noti che con l'assemblea GCC linea, non c'è bisogno di scrivere il codice che carica i tuoi operandi linguaggio assembly dalle espressioni C che producono i loro valori iniziali, o che memorizza i tuoi operandi risultato nella destinazione C.Ad esempio, si specifica che deve esserci un operando di input di tipo "r" (registro) derivato dall'espressione foo->bar + 1. GCC alloca il registro e genera il codice per caricarlo da foo->bar + 1 e quindi sostituisce le occorrenze di %0 nel modello di assieme con il nome di tale registro.

+2

+1, una risposta molto sofisticata alla domanda di follow-up dell'OP :) –

+0

# 2 è stato un commento molto utile, non ne avevo idea! Grazie! :) – Mehrdad

+0

in 1. sopra dice: * "L'idea è di generare, ed evitare l'analisi" * eppure mi sembra che per il compilatore ricevere le informazioni sugli oggetti danneggiati comporta comunque l'analisi, giusto? Venendo dall'impressione -possibilmente errata- che "l'assemblaggio in linea potrebbe non avere l'obiettivo di aumentare l'indipendenza dell'architettura, e sarà abbastanza facilmente l'assemblaggio essere specifico per la piattaforma", sarebbe bello che ci fosse un dizionario che fornisse le informazioni colpite dal compilatore , invece di permettere ai programmatori di dimenticare le cose. C'è stato qualche sviluppo da quando la domanda è stata data 2012? – humanityANDpeace

4

Citazione di the docs:

Quando si utilizza __asm ​​di scrivere in linguaggio assembly in C/C++ funzioni, non è necessario per preservare l'EAX, EBX, ECX, EDX, ESI, EDI o registri. Ad esempio, nell'esempio POWER2.C in Writing Functions with Inline Assembly, la funzione power2 non conserva il valore nel registro EAX. Tuttavia, l'utilizzo di questi registri influisce sulla qualità del codice poiché l'allocatore di registri non può utilizzarli per memorizzare i valori tra i blocchi __asm. Inoltre, utilizzando EBX, ESI o EDI nel codice assembly inline, si forza il compilatore a salvare e ripristinare quei registri nel prologo della funzione e nell'epilogo.

È necessario conservare altri registri utilizzati (come registri DS, SS, SP, BP e flag) per l'ambito del blocco __asm. È necessario conservare i registri ESP ed EBP a meno che non si abbia qualche motivo per cambiarli (per cambiare stack, ad esempio). Vedi anche Optimizing Inline Assembly.

+0

+1 mi sento così sciocco a non guardarlo nei documenti ... – Mehrdad

+1

Un po 'di domande la domanda però: perché GCC non fa questo? – Mehrdad

+2

Riassumendo per gli altri nostri lettori: "sì, MSVC rileva automaticamente quali registri sono danneggiati, mentre GCC richiede di contrassegnarli esplicitamente." – Crashworks

Problemi correlati