Domanda:
Dove vengono memorizzate le variabili statiche?
Swanand
2012-06-18 17:34:13 UTC
view on stackexchange narkive permalink

Supponiamo che io stia usando un 8051. Ho compilato un codice che ha una variabile statica. Dove verrà memorizzata quella variabile statica? Nella RAM? In Stack? On Heap ?? In flash? Dove?

Inoltre, correggimi se sbaglio: i CONST sono memorizzati nella ROM. E le variabili globali sono memorizzate in Flash. (E se non ho Flash?)

Mi aspetto risposte riguardo alla programmazione incorporata. Non è come in Code Segment o in .bss, ma esattamente dove sulla mia scheda?

Mi aspetto che le variabili statiche vengano memorizzate nello stesso posto delle variabili globali. Dopotutto, sono la stessa cosa con una portata diversa. (fammi sapere se sbaglio)
Sei risposte:
Turbo J
2012-06-18 18:04:30 UTC
view on stackexchange narkive permalink

Supponiamo che io stia usando un 8051.

Allora dovreste conoscere la memoria CODE, DATA, IDATA, XDATA e PDATA - 8051 è un'architettura multi Harvard.

Dove verrà memorizzata quella variabile statica?

Questa è una buona domanda. Dipenderà dalle impostazioni del compilatore, solitamente chiamate "modello di memoria"; Ma puoi anche dire esplicitamente dove lo metterà il compilatore:

  xdata unsigned int i; // numero intero nella memoria XDATA  

Il compilatore / linker dovrebbe essere in grado di creare un file Map, che mostrerà gli indirizzi delle tue variabili.

I CONST sono memorizzati nella ROM.

Questo probabilmente dipende dal compilatore e deve essere verificato con il file Map. Ricordo di averli etichettati esplicitamente:

  code const char fooStr [] = "Foo"; // stringa costante in code = memoria flash  

E le variabili globali sono memorizzate in Flash

Sia vero che falso. Risiedono in una delle memorie dati dell'8051, ma il valore iniziale verrà caricato da Flash all'avvio, a meno che la variabile non sia inizializzata con zero.

0x6d64
2012-06-18 17:58:43 UTC
view on stackexchange narkive permalink

La seguente risposta si basa sulla mia esperienza nell'analisi dei file di mappa, se mi sbaglio su qc. per favore correggimi!

Le variabili statiche non sono sicuramente memorizzate nell'heap, poiché questo è solo per le variabili allocate durante il tempo di esecuzione (e le variabili statiche sono allocate durante la fase di compilazione).

Le variabili statiche sono memorizzate nella RAM, proprio come le variabili globali. L'ambito di una certa variabile è importante solo per il compilatore, a livello di codice macchina nessuno ti impedisce di leggere una variabile locale al di fuori di una funzione (a condizione che il tuo controller non abbia alcune caratteristiche fantasiose per proteggere le aree di memoria dall'accesso) .

E le variabili globali sono memorizzate in Flash.

No. Pensaci: per scrivere un singolo bit di flash, devi cancellare un intero blocco di dati e poi riscrivere il tutto con i dati modificati. E questi passaggi non vengono eseguiti in un singolo ciclo come fa un semplice archivio nella RAM. Le variabili globali sono memorizzate nella RAM, proprio come accennato prima. Questo risolve anche la tua confusione sui sistemi senza flash.

Le "variabili statiche" note al momento della compilazione non sono variabili, ma costanti. Le variabili statiche vengono assegnate e modificate in fase di esecuzione. La differenza con le altre variabili è il loro ambito e durata: esistono finché esiste il programma.
@stevenvh: Mi vengono in mente esempi di variabili statiche, che certamente non sono costanti. Se avessi ragione, non significherebbe che la parola chiave `const` sarebbe inutile?
Hai modificato la tua risposta, ma il modo in cui è stata formulata sembrava essere nota in fase di compilazione era il criterio di base per chiamarla statica. Puoi definire perfettamente variabili statiche il cui valore non è noto in fase di compilazione; puoi dichiararli senza assegnazione.
supercat
2012-06-18 20:35:10 UTC
view on stackexchange narkive permalink

Sui processori in cui l'archivio del codice si trova nello stesso spazio degli indirizzi di tutte le altre variabili, i compilatori in genere inseriscono le variabili globali o statiche "const" qualificate nella propria sezione di collegamento e i linker saranno tipicamente configurati per posizionare quella sezione l'archivio del codice del sistema (flash, OTP o altro). Ciò ridurrà la quantità di RAM richiesta dal programma e ridurrà la quantità di lavoro che il codice di avvio deve fare.

Sui processori in cui l'archivio del codice si trova in uno spazio di indirizzi diverso (ad esempio il PIC o 8051), alcuni compilatori useranno un qualificatore const per segnalare che dovrebbero inserire le variabili nell'archivio del codice e utilizzare istruzioni diverse per accedervi, mentre altri no. Tali compilatori richiederanno che solo i puntatori con un qualificatore const possano essere usati per accedere alle variabili dichiarate const , poiché senza quel requisito i compilatori non saprebbero che istruzioni speciali devono essere utilizzato per accedere a tali puntatori.

Sui compilatori 8051 che ho visto (Archimedes e Keil), sono disponibili parole chiave specifiche del compilatore 8051 __data, __idata, __code, __bdata, _ pdata e _xdata disponibili per indicare tali variabili dovrebbe essere caricato in un particolare spazio di indirizzi. Per impostazione predefinita, i nomi possono essere utilizzati con o senza trattini bassi; le versioni senza trattino basso sono più convenienti, ma possono essere disabilitate se, ad es. si sta eseguendo il porting di un programma che utilizza identificatori denominati code o data ). Se un puntatore viene dichiarato senza applicare una di queste parole chiave alla sua destinazione, il compilatore allocherà tre byte: uno per indicare in quale spazio di memoria si trova la destinazione e due per contenere un indirizzo a 16 bit, se necessario. Dichiarare una variabile const senza applicare anche un qualificatore code farà sì che la variabile venga posizionata nello spazio degli indirizzi RAM predefinito e caricata con il valore predefinito all'avvio; una variabile dichiarata in questo modo può essere passata al codice che si aspetta un puntatore nello spazio degli indirizzi predefinito (ma utilizzerà la RAM). L'aggiunta di una dichiarazione __code (o code , se abilitata) farà sì che la variabile venga inserita nello spazio codice. Di solito è meglio usare la dichiarazione code piuttosto che no, ma in alcuni casi, specialmente se l'elemento in questione è piccolo, la relativa facilità di accesso alle cose nella RAM idata potrebbe rendere per la perdita di pochi byte di quello spazio.

Robert
2012-06-18 18:43:00 UTC
view on stackexchange narkive permalink

Risposta parziale: "Inoltre, correggimi se sbaglio: i CONST sono memorizzati nella ROM."

Errato. La parola chiave "const" è una direttiva per aiutare il compilatore. Quando una variabile viene dichiarata come "const", il compilatore sa che non può cambiare, ma è comunque una variabile a cui è assegnata una posizione di memoria.

Se è necessario / si desidera memorizzarla nella ROM, è necessario dovrà utilizzare un'altra parola chiave per il compilatore che gli dica quale tipo di memoria o posizione utilizzare. Non penso che ci sia una parola chiave standardizzata per questo. Probabilmente perché C è nato su un PC con tutto lo spazio del programma e lo spazio variabile come RAM.

Per un PIC, useresti la parola chiave "rom" per dichiarare la variabile.

ad es. "rom int const x = 42; '

Il posizionamento di una variabile _const_ a volte è controllato da una parola chiave non standard. Notare che c'è spesso un modo per configurare il linker per definire dove sono memorizzate le variabili _const_. Questo, ovviamente, varia con ciascuna catena di strumenti.
old_timer
2016-03-11 21:36:41 UTC
view on stackexchange narkive permalink

Statico implica che la variabile sia isolata da quel file / funzione / area di codice. Il luogo in cui è definito è visibile solo lì e quando viene utilizzato su non globali trasforma essenzialmente quella variabile in una globale dal punto di vista dell'archiviazione. Una variabile locale con una definizione statica significa che non voglio perdere quel valore da una chiamata di questa funzione a un'altra, quindi deve essere memorizzata globalmente per quella funzione, normalmente una variabile locale è sullo stack in modo che la funzione possa essere ri- entrant (una nuova copia delle variabili locali per ogni voce nella funzione). Quindi le variabili globali statiche sono comunque globali, le variabili locali statiche sono locali ma memorizzate insieme alle globali. In quello che viene spesso chiamato .data ma le toolchain possono avere nomi diversi. Questa è fondamentalmente la ram / memoria (lettura / scrittura) in cui sono archiviate le altre variabili globali o in cui vengono inizializzate le variabili quando definite

  int x = 7;  

vengono memorizzati. Le variabili globali o le variabili locali statiche che non vengono inizializzate quando definite

  int y;  

si trovano in quello che viene spesso chiamato .bss. Questo è un altro pezzo di memoria di lettura / scrittura, ma questa memoria prima di avviare main () viene azzerata per te in modo che per le specifiche o per assunzione quelle variabili siano zero all'avvio del programma.

const è un modo di dire che lo dichiaro come una variabile di sola lettura, non ho intenzione di memorizzarlo solo leggendo da esso. Quindi il compilatore può scegliere (in realtà è il programmatore poiché alla fine determina ciò che fa il linker, spesso lasciando che lo script del linker predefinito venga utilizzato e non assumendo quel lavoro) se va a flash o ram, può andare in qualsiasi posto e funzionare bene.

Per microcontrollori e altri luoghi in cui è necessario avviare e avviare l'esecuzione da una memoria non volatile (flash / rom / ecc.). Prima di tutto il programma stesso deve essere memorizzato in qualcosa di non volatile. Successivamente le cose .data, le cose che hai inizializzato nel tuo codice durante la definizione della variabile, cose che possono essere determinate in fase di compilazione. deve anche trovarsi in una memoria non volatile, ma alla fine i dati vengono letti / scritti, quindi il codice di bootstrap che viene eseguito prima che venga chiamato main (), fa il lavoro di copiare i blocchi .data nella memoria di lettura / scrittura. Il codice .bss o le variabili locali globali o statiche che non sono inizializzate e si presume siano zero quando si avvia, quelle non hanno bisogno di memoria non volatile, solo la posizione e quanto ne ha, e da questo il bootstrap può azzerare quella lettura / scrivere la memoria.

Ci sono ragioni per cui comunichiamo usando termini come .text, .data, .bss, .rodata, ecc. Perché vediamo che gli strumenti posizionano gli elementi del nostro programma in quei posti e poi noi può vedere dove devono vivere quei luoghi nella memoria non volatile e quindi durante il runtime se è diverso. .testo sebbene sciocco, è il nostro programma, il codice macchina e altri dati associati. .data sono variabili del nostro programma che vengono inizializzate prima di iniziare a essere diverse da zero, quindi devono essere archiviate in una memoria non volatile e quindi spostate in lettura / scrittura prima di utilizzarle. .bss sono variabili del nostro programma che si presume siano zero quando iniziamo, quindi la quantità e la posizione devono essere memorizzate in non volatile e il boostrap può eseguire l'azzeramento (o talvolta sono semplicemente memorizzate come un gruppo di zeri in anche il flash / rom). .rodata a volte è separato è il const a volte i const si trovano in .text, .text e .rodata sono considerati di sola lettura quindi possono rimanere in flash se il tuo prodotto è in grado di gestirlo (i flash più recenti hanno problemi di lettura-disturbo quindi fuori dal flash su un microcontrollore non lo vuoi necessariamente fare, devi stare attento) o possono anche essere copiati su ram.

Poi ci sono i termini heap e stack, che spesso dopo il programma, se necessario, .bss e .data consumano una certa quantità di ram, spesso dagli indirizzi inferiori in su. poi il resto di quella ram viene diviso in heap e stack, a volte senza una linea continua tra di loro, programmi mal funzionanti possono avere l'heap e lo stack in collisione causando un crash. lo stack è spesso dall'alto verso il basso e l'heap è spesso dal basso verso l'alto, ma queste non sono regole rigide e veloci.

Dove sono queste sul tuo tabellone? beh, dipende sia dal chip che dalla scheda per quanto riguarda le opzioni, quindi alla fine spetta a te il programmatore decidere mentre controlli il processo di compilazione e collegamento. La maggior parte delle persone riceve un esempio o una toolchain che conosce il tuo sistema e lasci le impostazioni predefinite. Ma sei assolutamente responsabile. Affinché un microcontrollore si avvii devi avere un modo per farlo, di solito è un chip flash on o off a seconda del mcu, e le cose non volatili sopra menzionate devono essere memorizzate lì o in qualche altro posto non volatile . Allo stesso modo hai un po 'di RAM, devi dividerlo con le cose di lettura / scrittura di cui hai bisogno, inclusi stack e heap se sei abbastanza coraggioso da usarlo in un tale sistema (non saggio). Alcuni processori lo stack fa parte del design e non devi preoccuparti, altri lo fai. Se hai più di queste cose, ram non volatile o di lettura / scrittura, allora puoi scegliere e scegliere dove mettere le cose.

se usi una toolchain di qualcuno, o hai accesso a diversi lì non c'è motivo di presumere che faranno la stessa cosa con il tuo programma con il loro script di collegamento predefinito. di solito le toolchain forniscono file di mappe o altri modi per vedere dove hanno posizionato le cose per te.

è certamente possibile avere un sistema basato su microcontrollore senza flash, ogni sentire di un mouse o di una tastiera? Alcuni dei insieme a molti altri prodotti possono funzionare senza queste cose. Alcuni potrebbero ad esempio avere nella logica del chip per gestire l'enumerazione usb, quindi il driver del sistema operativo per quel prodotto contiene il firmware, scarica il firmware nella ram sul dispositivo e avvia il processore e forse enumera nuovamente l'USB così che ora è un topo o qualsiasi altra cosa. non tutti lo fanno ma a volte è fatto. Allo stesso modo potresti avere qualche altro design in cui qualche altro hardware o soluzione scarica il programma nel chip / ram prima di avviare il processore in modo efficace, facendo sembrare che il processore non abbia flash. Ma hai ancora gli stessi concetti .text, .data, .bss e il programma che esegui, sia esso solo ram, era ancora compilato in programma, zero dati di inizializzazione e dati di inizializzazione diversi da zero e al linker doveva essere detto dove posiziona queste cose nel binario e aggiorna il codice per sapere dove il linker ha posizionato le variabili che deve usare.

AlphaGoku
2016-03-11 15:50:38 UTC
view on stackexchange narkive permalink

Sebbene la tua domanda sia correlata all'8051 e siano state suggerite molte risposte giuste, vorrei anche includere una risposta per le persone che arrivano qui semplicemente leggendo la tua domanda e non i dettagli. Vorrei fornire alcuni collegamenti per l'architettura ARM sulla serie LPC di microcontrollori che utilizzano Keil IDE. Questi sono alcuni collegamenti importanti che mi hanno aiutato a capire il comportamento di dove sono posizionate le variabili:



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...