Se un processore a 32 bit può gestire circa 4 GiB di RAM (ovvero ) byte, perché il mio Arduino Mega 2560 ha 8 KiB di SRAM, se essere un processore a 8 bit gli consente di gestire solo 256 byte ( )? O sto leggendo la pagina seguente sbagliata?
Se un processore a 32 bit può gestire circa 4 GiB di RAM (ovvero ) byte, perché il mio Arduino Mega 2560 ha 8 KiB di SRAM, se essere un processore a 8 bit gli consente di gestire solo 256 byte ( )? O sto leggendo la pagina seguente sbagliata?
Risposte:
La maggior parte delle CPU a 8 bit ha bus di indirizzo a 16 bit che consentono loro di indirizzare 64kbyte, proprio perché 256 byte in realtà non sono sufficienti per fare molto! Significa solo che devono caricare due byte anziché uno, ogni volta che devono caricare un indirizzo. Leggermente più lento ma tollerabile considerando le loro dimensioni.
(E sì, ci sono molte eccezioni, sviluppate principalmente quando 64k sono diventate troppo piccole, ma qui stiamo parlando dell'idea di base).
Il bus degli indirizzi e il bus dei dati sono separati, pertanto possono avere dimensioni diverse. Per qualsiasi dimensione specifica del bus dell'indirizzo ci sono molte tecniche per indirizzare più memoria della larghezza del bit del registro
Il modo più comune è in qualche modo aumentare la larghezza del bus dell'indirizzo
utilizzando più registri per l'indirizzo
X
, Y
e Z
dati di indirizzamento registri per consentire il massimo 64 KB di RAM. Coloro che a sua volta può essere accoppiato con RAMPX
, RAMPY
, RAMPZ
di accedere agli indirizzi di RAM più elevati nelle versioni ancora più grandi. Ha anche SPH
per i byte alti del puntatore dello stack oltre alle SPL
varianti con più di 256 byte di RAM 1H
& L
, B
& C
, D
e E
che possono essere utilizzate insieme come registro indirizzi a 16 bitutilizzando un unico grande registro speciale più grande della dimensione naturale per l'indirizzamento
utilizzando un registro speciale per la parte alta dell'indirizzo . Quando si indirizza un po 'di memoria, per impostazione predefinita gli 8 bit bassi dell'indirizzo saranno presi dal registro immediato a 8 bit o 8 bit su un microcontrollore a 8 bit, mentre i bit alti saranno sostituiti dal valore del registro dell'altro indirizzo.
call
o l' goto
istruzione, 8 o 9 bit bassi dell'indirizzo sono indicati dall'immediato e il resto è preso dal contatore del programma corrente. Pertanto, l'accesso a qualsiasi cosa non lontano dal segmento corrente utilizza solo 1 istruzione, mentre ulteriori indirizzi avranno bisogno di 2 istruzioni (per impostare i bit alti).PC
mentre salta incondizionatamente.Un altro modo per raggiungere questo obiettivo è la memoria bancaria . Questo è un metodo utile ancora oggi utilizzato in alcune architetture. In questo modello, la memoria è divisa in più banchi . Ogni volta che puoi rivolgersi solo a una banca specifica. Esistono spesso una banca globale o un intervallo di indirizzi che sono sempre visibili in qualsiasi momento, ma per altre parti è necessario cambiare banca quando necessario.
C'è anche una tecnica non abbastanza comune ma può essere trovata nell'Intel 8051 . Come microcontrollore con indirizzo dati a 8 bit, può avere al massimo 256 indirizzi. La metà dello spazio (la parte alta) viene utilizzata per registri di funzioni speciali ( SFR ), limitando la RAM reale indirizzabile a soli 128 byte. Tuttavia, i moderni produttori della serie 8051 hanno trovato un modo intelligente per superare ciò separando l'accesso alla memoria . L'indirizzamento diretto accederà all'SFR mentre l'indirizzamento indiretto sebbene i registri accedano alla parte alta della RAM, il che significa che ora hai 256 + 128 = 384 byte indirizzabili.
1 https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Memory_addressing_instructions
I core più piccoli hanno ≤256 byte di spazio degli indirizzi dei dati (che significa ≤128 byte di RAM dopo che le porte I / O e altri indirizzi riservati sono stati rimossi) e ≤8192 byte (8 KiB) della ROM del programma. Questi hanno solo un puntatore di stack a 8 bit (in SPL) e supportano solo le istruzioni relative al salto / chiamata relative a 12 bit RJMP / RCALL. (Poiché il contatore del programma AVR conta parole a 16 bit, non byte, un offset a 12 bit è sufficiente per indirizzare 213 byte di ROM.)
Funzionalità di indirizzamento della memoria aggiuntive sono presenti come richiesto per accedere alle risorse disponibili:
- I modelli con> 256 byte di spazio di indirizzi dati (≥256 byte di RAM) hanno un puntatore di stack a 16 bit, con la metà superiore nel registro SPH.
- I modelli con> 8 KiB di ROM aggiungono le istruzioni JUMP e CALL di 2 parole (22 bit). (Alcuni primi modelli subiscono un errore se un'istruzione skip è seguita da un'istruzione di 2 parole.)
- I modelli con> 64 KiB di ROM aggiungono l'istruzione ELPM e il corrispondente registro RAMPZ. Le istruzioni LPM a zero estendono l'indirizzo ROM in Z; Le istruzioni ELPM antepongono il registro RAMPZ per bit alti. Questa non è la stessa cosa dell'istruzione LPM più generale; esistono modelli "classici" con solo la forma di ELPM operando zero (ATmega103 e at43usb320). Quando è disponibile l'incremento automatico (la maggior parte dei modelli), aggiorna l'intero indirizzo a 24 bit incluso RAMPZ.
- I modelli (rari) con> 128 KiB di ROM hanno un contatore di programmi a 3 byte. Le chiamate e i ritorni di subroutine utilizzano un byte aggiuntivo di spazio dello stack, esiste un nuovo registro EIND per fornire bit alti aggiuntivi per salti e chiamate indirezionali e ci sono nuove istruzioni estese EIJMP ed EICALL che utilizzano EIND: Z come indirizzo di destinazione. (Le precedenti istruzioni IJMP e ICALL utilizzano Z con estensione zero.)
- I modelli (rari) con> 64 KiB di spazio di indirizzi RAM estendono i limiti di indirizzamento RAM a 16 bit con i registri RAMPX, RAMPY, RAMPZ e RAMPD. Questi forniscono bit alti aggiuntivi per le modalità di indirizzamento che utilizzano rispettivamente le coppie di registri X, Y o Z o le istruzioni di indirizzamento diretto LDS / STS. A differenza dell'accesso alla ROM, non ci sono istruzioni "estese" distinte; invece i registri RAMP sono usati incondizionatamente.
Quasi tutti i processori a 8 bit hanno una certa capacità di formare un indirizzo a 16 bit da una parte di ordine inferiore e una parte di ordine superiore. Su alcuni processori incluso l'8080 originale, ci sono registri dedicati a contenere la parte superiore e inferiore di un indirizzo (anche se dal punto di vista di un programmatore potrebbero esserci dei registri come il puntatore dello stack dell'8080 che non offrono istruzioni per affrontarli separatamente). In alcuni altri processori, non ci sono registri dedicati alla metà superiore o inferiore di un indirizzo, ma gli indirizzi sono assemblati "al volo". Ad esempio, sul 6502, l'istruzione "LDA $ 1234, X" carica l'accumulatore con l'indirizzo formato aggiungendo $ 1234 al registro X a 8 bit [supponiamo che contenga $ F0]. L'esecuzione di tale istruzione procederebbe in 4 o 5 passaggi:
Il trasferimento del byte letto all'accumulatore si sovrapporrà al recupero dell'istruzione successiva. Inoltre, per molte operazioni, se il passaggio 3 non ha generato un carry, il passaggio 4 avrebbe letto l'indirizzo corretto e l'esecuzione potrebbe saltare direttamente dal passaggio 4 all'istruzione successiva, ignorando il passaggio 5.
Se si esamina la sequenza delle operazioni, si noterà che un'architettura little-endian ha un netto vantaggio rispetto a una big-endian, in questo nella maggior parte dei casi (anche se non quella mostrata), anche se l'ALU impiega un ciclo per eseguire inoltre, è possibile leggere un byte dall'indirizzo calcolato senza attendere il risultato ALU, poiché normalmente il byte alto che è stato prelevato sarà il byte alto dell'operando di destinazione. Su una macchina big-endian con un ALU a 8 bit, un carico indicizzato richiederebbe almeno 5 cicli (poiché la metà inferiore dell'indirizzo non verrebbe letta fino al passaggio 3 e verrebbe quindi calcolata al passaggio 4).
Le righe del databus (pin) e le righe dell'indirizzo (pin) sono completamente separate. In poche parole, le linee di database determinano il numero massimo di bit che possono essere trasferiti uno alla volta (e memorizzati nella memoria), mentre le linee di indirizzo determinano il numero massimo di "celle" di memoria che è possibile selezionare.
Per lo più era una questione di marketing che le CPU x86 a 32 bit non potessero indirizzare più di 4 GB di RAM. Ricordo che da qualche parte c'erano pin A33-34 sulle CPU Pentium 4.
È spesso vero che esiste una relazione tra la dimensione della memoria indirizzabile e la dimensione del registro interno, sebbene la relazione vari per diversi motivi. 256 byte di spazio di indirizzi erano considerati troppo piccoli anche ai primissimi tempi dei microprocessori, quindi la maggior parte dei processori a 8 bit produceva indirizzi a 16 bit (due byte), che indirizzavano a 64 kilobyte. Con il cambio di banca, però (essenzialmente utilizzando determinate linee I / O per produrre ancora più linee di indirizzo), era possibile avere molto di più.
Nei primi processori a 16 e 32 bit, non c'erano sempre abbastanza pin sul dispositivo per raggiungere tutto lo spazio che i loro registri di indirizzi interni potevano indirizzare. Ad esempio, sul Motorola 68000, c'erano solo abbastanza pin di indirizzo (24) per indirizzare 16 megabyte di RAM, sebbene i registri degli indirizzi interni fossero larghi 32 bit.
Risponderò a questa domanda specificamente per i controller AVR che hai citato. Il principio di base vale anche per molte altre architetture a 8 bit.
Gli AVR sono core a 8 bit. Ciò significa che hanno registri a 8 bit. Tuttavia, 8 bit non sono sufficienti per accedere a una quantità utilizzabile di memoria. Pertanto, il core AVR è in grado di utilizzare un set specifico di registri combinato come registri puntatore a 16 bit. I registri r30 e r31 (anche aliasati come ZL e ZH) ne sono un esempio. Insieme formano il puntatore Z.
Nell'assembly leggere un byte all'indirizzo 0x1234 sarebbe simile al seguente:
ldi ZL, 0x34 ; Load r30 (ZL) with low byte of address
ldi ZH, 0x12 ; Load r31 (ZH) with high byte of address
ld r16, Z ; Load byte to r16
La famiglia AVR ha 3 coppie di registri che possono essere utilizzate per questo. Sono specificamente progettati in hardware per consentire tali operazioni.
Durante la programmazione in un linguaggio di livello superiore come C, il compilatore gestisce queste cose.
Nota: alcuni AVR supportano persino dimensioni di memoria maggiori di 64k. Questi controller dispongono di un registro di funzioni speciali in cui vengono scritti bit aggiuntivi dell'indirizzo prima dell'accesso. L'indirizzo è quindi composto dai seguenti bit (da MSB a LSB):
Registro delle funzioni speciali (di solito 1 byte), ZH (8 bit), ZL (8 bit).
Gli AVR a 8 bit di Atmel utilizzano effettivamente un indirizzo dati a 16 bit. Hanno numerosi altri registri a 16 bit e persino alcuni timer a 16 bit. Poiché è solo un processore a 8 bit, di solito utilizza due cicli di clock per caricare un registro a 16 bit.
Wikipedia lo spiega abbastanza bene:
Le CPU a 8 bit utilizzano un bus dati a 8 bit e possono quindi accedere a 8 bit di dati in una singola istruzione macchina. Il bus dell'indirizzo è in genere un doppio ottetto largo (cioè 16 bit), a causa di considerazioni pratiche ed economiche. Ciò implica uno spazio di indirizzamento diretto di soli 64 KB sulla maggior parte dei processori a 8 bit.
L'idea che la "larghezza di bit" di un processore stabilisca la massima quantità di RAM che il processore può affrontare è uno dei miti più pervasivi nell'informatica. In effetti la storia del settore è piena di CPU per le quali questa relazione non è stata mantenuta.
HP 21MX, HP 1000: CPU a 16 bit, memoria a 16 MB
PDP-11: CPU a 16 bit, memoria a 4 MB
VAX-11/780: CPU a 32 bit, memoria a 512 MB
ecc. ecc.