Perché la prima istruzione BIOS si trova su 0xFFFFFFF0 ("top" di RAM)?


51

So che il BIOS carica le sue prime istruzioni da 0xFFFFFFF0, ma perché questo indirizzo specifico? Ho un sacco di domande e spero che tu possa aiutarmi con alcune di esse, almeno.

Le mie domande:

  • Perché la prima istruzione BIOS si trova nella parte superiore di una RAM da 4 GB?
  • Cosa succederebbe se il mio computer avesse solo 1 GB di RAM?
  • Che dire dei sistemi con più di 4 GB di RAM (ad esempio 8 GB, 16 GB, ecc.)?
  • Perché lo stack è inizializzato con un valore (in questo caso, un valore situato su 0xFFFFFFF0)?

Ne ho letto questo pomeriggio e ancora non capisco.


28
Una domanda per domanda per favore.
Corse di leggerezza con Monica,

4
Mi piace come la risposta accettata non menzioni nemmeno la memoria segmentata o le modalità di indirizzamento e l'unico posto in cui la linea A20 viene persino toccata è nei commenti.
imallett,

Gli AVR Atmel iniziano l'esecuzione dall'indirizzo 0, mentre quelli di Freescale HCS08 iniziano da 0xFFFE, iirc. Ogni famiglia di processori ha le sue caratteristiche.
Nick T

2
@imallett Mi piace come decidi di lamentarti qui invece di chiedere al poster di aggiornare la loro risposta con ulteriori informazioni. Mi piace anche come pensi che questa conoscenza che OP sarebbe in grado di individuare anche se lo scopo di porre una domanda è quella di ottenere informazioni su cose che ora si potrebbero comprendere appieno.
MonkeyZeus,

2
Ad oggi @MonkeyZeus, altri 9 commentatori l'hanno già fatto e non è ancora cambiato. Il mio commento, sebbene sarcastico, non era vacuo; è un avvertimento per i futuri cittadini della rete, nonché per il PO.
imallett,

Risposte:


57

0xFFFFFFF0è dove una CPU compatibile x86 inizia a eseguire le istruzioni quando è accesa. Questo è un aspetto cablato, immutabile (senza hardware aggiuntivo) della CPU e diversi tipi di CPU si comportano in modo diverso.

Perché la prima istruzione BIOS si trova nella parte superiore di una RAM da 4 GB?

Si trova nella parte superiore dello spazio degli indirizzi da 4 GB e all'accensione il BIOS o la ROM UEFI è impostato per rispondere alle letture di tali indirizzi.

La mia teoria sul perché questo è:

Quasi tutto nella programmazione funziona meglio con indirizzi contigui. Il progettista della CPU non sa cosa vorrà fare un system builder con la CPU, quindi è una cattiva idea per la CPU richiedere indirizzi nel mezzo dello spazio richiesti per vari scopi. È meglio tenerlo "fuori mano" nella parte superiore o inferiore dello spazio degli indirizzi. Naturalmente, tieni presente che questa decisione è stata presa quando l'8086 era nuovo, che non aveva un MMU .

Nell'8086 esistevano vettori di interruzione nella posizione di memoria 0 e superiore. I vettori di interruzione devono trovarsi a indirizzi noti e si desiderava che si trovassero nella RAM per flessibilità - tuttavia non era possibile per il progettista della CPU sapere quanta RAM sarebbe stata in un sistema. Quindi a partire da 0 e lavorando su aveva senso per quelli (perché nessun sistema nel 1978 quando fu inventato l'8086 avrebbe avuto 4 Gbyte di RAM - quindi aspettarsi che la RAM fosse a 0xFFFFFFF0 non era una buona idea), e quindi la ROM avrebbe dovuto essere al limite superiore.

Naturalmente, a partire almeno dall'80286, i vettori di interruzione potrebbero essere spostati in una posizione di partenza diversa da 0, ma le moderne CPU x86 a 64 bit si avviano ancora in modalità 8086, quindi tutto funziona ancora alla vecchia maniera per compatibilità (come ridicolo come sembra nel 2015 avere ancora bisogno della tua CPU x86 per poter eseguire DOS).

Quindi, poiché i vettori di interruzione iniziano da 0 e funzionano verso l'alto, la ROM dovrebbe iniziare dall'alto e lavorare verso il basso.

Cosa succederebbe se il mio computer avesse solo 1 GB di RAM?

Una CPU a 32 bit ha 4.294.967.296 indirizzi, numerati da 0 (0x00000000) a 4294967295 (0xFFFFFFFF). La ROM può vivere in alcuni indirizzi e la RAM può vivere in altri. Con la MMU della CPU questo può anche essere commutato al volo. La RAM non deve vivere a tutti gli indirizzi.

Con solo 1 GB di RAM, alcuni indirizzi non risponderanno nulla quando vengono letti o scritti. Ciò può causare la lettura di dati non validi quando si accede a tali indirizzi o un blocco del sistema.

Che dire dei sistemi con più di 4 GB di RAM (ad esempio: 8 GB, 16 GB, ecc.)?

Semplificando un po ': le CPU a 64 bit hanno più indirizzi (che è una delle cose che li rende a 64 bit, ad esempio da 0x0000000000000000 a 0xFFFFFFFFFFFFFFFF), quindi la RAM aggiuntiva "si adatta". Supponendo che la CPU sia in modalità lunga . Fino ad allora la RAM è lì, semplicemente non indirizzabile.

Perché lo stack è inizializzato con un valore (in questo caso, un valore situato su 0xFFFFFFF0)?

Non riesco a trovare immediatamente nulla su ciò che x86 assegna il puntatore dello stack all'accensione, ma alla fine dovrebbe essere riassegnato da una routine di inizializzazione una volta che quella routine ha scoperto quanta RAM è presente nel sistema. (@Eric Towers nei commenti seguenti riporta che è impostato su zero all'accensione.)


7
È meglio pensare allo spazio degli indirizzi come a un grande spazio in cui le cose possono essere assegnate dall'hardware. Quando la CPU legge / scrive memoria, in realtà esegue una comunicazione su un bus e l'hardware può assicurarsi che cose come RAM o ROM rispondano a intervalli di indirizzi specifici. Quindi, tale hardware dovrebbe assicurarsi che una ROM risponda a 0xFFFFFFF0 quando la CPU viene ripristinata. Non esiste alcun obbligo intrinseco che la ROM appaia subito dopo la RAM. Può apparire ovunque l'hardware lo dica anche, a seconda delle capacità di tale hardware.
LawrenceC

4
È possibile avere "buchi" o spazi non assegnati che non sono utilizzati da ROM, RAM o altro - in genere l'accesso a questi causerà un blocco del sistema.
LawrenceC

16
Questa risposta presuppone che la CPU possa utilizzare 32 bit di indirizzo in modalità 16 bit. Ma in modalità 16 bit può usare solo 20 bit di indirizzo. L'indirizzo 0xFFFFFFF0non è raggiungibile fino a quando la CPU non è passata alla modalità a 32 bit. L'ultima volta che ho esaminato attentamente il codice BIOS, il punto di ingresso era 0xFFFF0.
Kasperd,

6
@ MichaelKjörling il tuo calcolo è sbagliato. Il segmento e l'offset spostati non sono OR, ma vengono aggiunti. Pertanto, FFFF logico: FFF0 è fisico (1) 0FFE0 (dove 1 iniziale è presente se A20 è abilitato).
Ruslan,

9
@kasperd È presente un hack: il gestore della memoria ha i 12 bit alti impostati su 1 fino al primo salto in lungo. Quindi sì, logicamente, stai lavorando 0xFFFF0, ma in realtà, è mappato a 0xFFFFFFF0. Mi aspetto che questo è stato fatto per la compatibilità con il 8086 - sia esso e le CPU più moderne sembrano ad uso 0xFFFF0, ma le CPU a 32-bit in realtà l'accesso 0xFFFFFFF0(mappato ROM BIOS).
Luaan,

26

Non si trova nella parte superiore della RAM; si trova nella ROM il cui indirizzo si trova nella parte superiore dello spazio degli indirizzi di memoria, insieme a qualsiasi memoria sulle schede di espansione, come i controller Ethernet. È lì in modo che non sia in conflitto con la RAM, almeno fino a quando non hai installato 4 GB. I sistemi con almeno 4 GB di RAM possono fare due cose per risolvere il conflitto. Le schede madri economiche ignorano semplicemente le parti di RAM che sono in conflitto con la posizione della ROM. Quelli decenti rimappano che la RAM sembra avere un indirizzo sopra il segno da 4 GB.

Non sono sicuro di quello che stai chiedendo sulla pila. Certamente non è inizializzato per essere nella ROM. Quando la CPU viene ripristinata, inizialmente è in "modalità reale", dove si comporta esattamente come l'8086 originale e utilizza l'indirizzamento segmentato a 16 bit, consentendogli di accedere solo a 1 MB di memoria. Il codice BIOS si trova nella parte superiore di quel 1 MB. Il BIOS seleziona da qualche parte nella RAM per impostare lo stack e carica ed esegue il primo settore della prima unità avviabile. Spetta al sistema operativo passare alla modalità a 32 o 64 bit una volta che prende il controllo e imposta i propri stack (uno per attività / thread).


1
Grazie mille per la risposta, ma @LawrenceC fornisce maggiori dettagli sulla sua risposta e mi ha aiutato a capire come funziona tutto. Comunque grazie! Ti do un voto: 3
Fernando Paladini,

13

Innanzitutto, questo non ha nulla a che fare con la RAM, davvero. Stiamo parlando dello spazio degli indirizzi qui - anche se hai solo 16 MiB di memoria, hai ancora tutti i 32 bit di spazio degli indirizzi su una CPU a 32 bit.

Questo risponde già alla tua prima domanda, davvero - al momento in cui è stato progettato, i PC del mondo reale non avevano nulla vicino ai 4 GiB di memoria; erano più nel range di 1-16 MiB di memoria. Lo spazio degli indirizzi era, a tutti gli effetti, libero.

Ora, perché 0xFFFFFFF0 esattamente? La CPU non sa quanta parte del BIOS esiste. Alcuni BIOS possono richiedere solo pochi kilobyte, mentre altri possono occupare megabyte di memoria completa e non sto nemmeno entrando nelle varie RAM opzionali. Per iniziare, la CPU deve essere cablata a un determinato indirizzo: non è necessario configurare la CPU. Ma questa è solo una mappatura dello spazio degli indirizzi - l'indirizzo è mappato direttamente nel chip ROM del BIOS (sì, questo significa che non avrai accesso a tutti i 4 GiB di RAM a questo punto se ne hai così tanti - ma non è niente di speciale, molti dispositivi richiedono il proprio intervallo nello spazio degli indirizzi). Su una CPU a 32 bit, questo indirizzo fornisce 16 byte completi per eseguire l'inizializzazione di base, che è sufficiente per impostare i segmenti e, se necessario, la modalità indirizzo (ricorda,"procedura" di avvio reale . A questo punto, non usi affatto la RAM, è solo una ROM mappata. In effetti, la RAM non è nemmeno pronta per essere utilizzata a questo punto - questo è uno dei lavori del BIOS POST! Ora potresti pensare: come fa una modalità reale a 16 bit ad accedere all'indirizzo 0xFFFFFFF0? Certo, ci sono segmenti, quindi hai uno spazio di indirizzamento di 20 bit, ma non è ancora abbastanza buono. Bene, c'è un trucco: i 12 bit alti dell'indirizzo sono impostati fino a quando non esegui il tuo primo salto in lungo, dandoti accesso allo spazio di indirizzi alto (rifiutando l'accesso a qualcosa di inferiore a 0xFFF00000 - finché non esegui un salto in lungo) .

Tutto ciò è nascosto soprattutto ai programmatori (per non parlare degli utenti) sui moderni sistemi operativi. Di solito non hai accesso a nulla di così basso livello - alcune cose sono già al di là del recupero (non puoi cambiare le modalità della CPU in modo pessimo), altre sono gestite esclusivamente dal kernel del sistema operativo.

Quindi una visione migliore viene dalla codifica di vecchia scuola su MS DOS. Un altro esempio tipico di mappatura diretta della memoria del dispositivo nello spazio degli indirizzi è l'accesso diretto alla memoria video. Ad esempio, se volevi scrivere velocemente un testo sul display, scrivevi direttamente all'indirizzo B800:0000(più offset - in modalità testo 80x25, questo significava che (y * 80 + x) * 2se la mia memoria mi serve bene - due byte per carattere, riga per riga). Se volevi disegnare pixel per pixel, hai usato una modalità grafica e l'indirizzo iniziale di A000:0000(in genere, 320x200 a 8 bit per pixel). Fare qualsiasi cosa ad alte prestazioni di solito significava immergersi nei manuali dei dispositivi, per capire come accedervi direttamente.

Questo sopravvive fino ad oggi - è appena nascosto. Su Windows, puoi vedere gli indirizzi di memoria associati ai dispositivi in ​​Gestione dispositivi - apri le proprietà di qualcosa come la tua scheda di rete, vai alla scheda Risorse - tutti gli elementi del Range di memoria sono mappati dalla memoria del dispositivo al tuo spazio di indirizzi principale. E a 32 bit, vedrai che la maggior parte di quei dispositivi sono mappati sopra il segno 2 GiB (successivamente 3 GiB), ancora una volta, per ridurre al minimo i conflitti con la memoria utilizzabile dall'utente, sebbene questo non sia realmente un problema con la memoria virtuale ( le applicazioni non si avvicinano in alcun modo al reale spazio degli indirizzi hardware : hanno il loro pezzo di memoria virtualizzato, che potrebbe essere mappato su RAM, ROM, dispositivi o file di pagina, ad esempio).

Per quanto riguarda lo stack, beh, dovrebbe aiutare a capire che, per impostazione predefinita, lo stack cresce dall'alto. Quindi, se fai un push, il nuovo puntatore dello stack sarà su 0xFFFFFEC- in altre parole, non stai cercando di scrivere all'indirizzo di inizializzazione del BIOS :) Il che ovviamente significa che le routine di inizializzazione del BIOS possono usare lo stack in modo sicuro, prima di rimapparlo da qualche parte più utile. Nella programmazione di vecchia scuola, prima che il paging diventasse di fatto il default, lo stack di solito si avviava alla fine della RAM, e lo "overflow dello stack" si verificava quando si iniziava a sovrascrivere la memoria dell'applicazione. La protezione della memoria ha cambiato molto questo, ma in generale mantiene la retrocompatibilità il più possibile - nota come anche la più moderna CPU x86-64 può ancora avviare MS DOS 5 - o come Windows può ancora eseguire molte applicazioni DOS che non hanno idea del paging.


3
Risposta eccellente, solo per espandere e dire che i moderni processori stanno iniziando a eliminare gli hack come il mascheramento della linea A20 , quindi il supporto per i casi limite più vecchi sta morendo.
Base

2
All'ultimo paragrafo: il BIOS non può usare lo stack "liberamente": non può scrivere sulla ROM (alla quale 0xFFFFFFECverrebbe mappato). Questo significa non solo no, pushma per esempio no call. Questi devono attendere fino a quando la RAM è pronta.
The Vee,

7

In aggiunta agli altri punti menzionati, può essere utile per capire che cosa un indirizzo è . Mentre le architetture più recenti complicano le cose, storicamente una macchina su ogni ciclo di memoria produceva l'indirizzo desiderato su 20-32 fili (a seconda dell'architettura, con alcuni trucchi speciali per notare se fosse necessario una coppia o quattro di byte contemporaneamente); varie parti del sistema di memoria esaminerebbero lo stato di quei fili e si attiverebbero quando vedessero determinate combinazioni di valori alti e bassi.

Se una macchina con 32 fili di indirizzo avesse bisogno solo di usare 1 MB di RAM e 64 KB di ROM [abbastanza plausibile per alcuni controller integrati], potrebbe attivare la RAM per tutti gli indirizzi in cui il filo dell'indirizzo superiore era basso e la ROM per tutti gli indirizzi in cui si trovava alta. I 20 fili di indirizzo inferiori sarebbero quindi legati alla RAM per selezionare uno di 1.048.576 byte e anche i 16 inferiori sarebbero collegati alla ROM, per selezionare uno di 65.536 byte. I restanti 11 cavi di indirizzo non sarebbero semplicemente collegati a nulla.

Su tale macchina, gli accessi agli indirizzi 0x00100000-0x001FFFFF sarebbero equivalenti agli accessi agli indirizzi RAM 0x00000000-0x000FFFFF. Allo stesso modo con gli indirizzi 0x000200000-0x0002FFFFF o 0x7FF00000-0x7FFFFFFFF. Gli indirizzi superiori a 0x80000000 leggono tutti la ROM, con un modello da 64 KB che si ripete in tutto lo spazio.

Anche se il processore ha uno spazio di indirizzi di 4.294.967.296 byte, non è necessario che l'hardware riconosca molti indirizzi distinti. Mettere il vettore di ripristino vicino alla parte superiore dello spazio degli indirizzi è un progetto che funzionerà bene indipendentemente da quanta o quanta RAM e ROM ha il sistema ed evita la necessità di decodificare completamente lo spazio degli indirizzi.


Un buon punto: non troverai alcun hardware a 64 bit che supporterà qualcosa vicino allo spazio di memoria indirizzabile a 64 bit (o anche 1x10 ^ -12 di esso).
Base

3

La mia teoria è perché stiamo usando la logica negativa quella digitale (1) non è affatto tensione (O volt) All'inizializzazione dobbiamo solo mettere in tensione gli ultimi 4 bit, quindi il contatore del programma (o il puntatore dell'istruzione) lacera a 1111 1111 1111 1111 1111 1111 1111 0000. Non è necessario indirizzare i 28 bit superiori poiché la maggior parte dei (vecchi) cpu) erano 16 bit e i nibble inferiori possono essere indirizzati da un singolo chip di indirizzo ai vecchi tempi. Ora da quando abbiamo 64 bit con compatibilità a 32 bit e 32 bit a 16 bit, l'hardware è stato migliorato ma il metodo rimane. Inoltre, i biosi non sono sempre programmati a 64 bit o 32 bit. La mia opinione è anche dal momento che i ricordi non sono sempre gli stessi, il bios deve trovarsi nello stesso primo segmento. Il modo in cui vediamo il bios indirizzato non è sempre il vero indirizzo. Solo un mio insegnante ...


2

su RESET una CPU compatibile 8088/8086 esegue le istruzioni a 0FFFF0, che è 16 byte al di sotto del limite di 1 megabyte. normalmente la ROM in questa posizione (nelle implementazioni del PC) sarebbe il BIOS, quindi alla fine della ROM del BIOS, c'è un salto all'inizio della ROM del BIOS.

mostrato qui: avvia il vettore e la firma 'date' dietro di esso, IBM 5150 PC 8KB eprom dump bios data: 19/10/1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

si noti che gli indirizzi sono di una rom di $ 2000 da 8 KB, che posiziona l'indirizzo iniziale (il JMP assoluto assoluto, in qualunque altra posizione, in questo caso all'interno della rom da 8 KB, sebbene non l'indirizzo più basso possibile all'interno di quella rom) a $ FFFF: $ 0 segmentato o $ FFFF0 lineare.

per quanto riguarda la compatibilità: se un processore "futuro" o attuale "si aspetta" che abbia molte più F davanti all'indirizzo, non importa. per la compatibilità di cpus più recenti nei sistemi più vecchi le linee di indirizzo aggiuntive rimangono non connesse e quindi i dati sul database sono esattamente gli stessi. purché i bit meno significativi rimangano FFFF0.

(in un sistema con solo 1 mb di RAM e la rom posizionata alla fine di quella mazza, e nient'altro, "penserà" felicemente di parlare con l'indirizzo più alto ma otterrà esattamente gli stessi dati, perché quelle implementazioni non hanno mai sentito parlare indirizzo superiore a A19)

prendi nota che il mondo non è solo "pc" ... l'ibm pc è stato un "incidente", questi processori non sono mai stati progettati appositamente per i "pc" e vanno in molte altre cose oltre ai PC (come i satelliti, sistemi di armi, ecc.). Le modalità protette a 32 e 64 bit sono generalmente non desiderate. (la modalità 8086 virtuale è molto più interessante come motivo per scegliere una versione più recente (386+) per esempio). quindi c'è molto di più nella "retrocompatibilità" oltre al semplice "funzionerà dos".


1

La scheda madre garantisce che l'istruzione sul vettore di ripristino sia un salto alla posizione della memoria mappata al punto di ingresso del BIOS. Questo salto cancella implicitamente l'indirizzo di base nascosto presente all'accensione. Tutte queste posizioni di memoria hanno i giusti contenuti necessari alla CPU grazie alla mappa di memoria mantenuta dal chipset. Sono tutti mappati sulla memoria flash contenente il BIOS poiché a questo punto i moduli RAM hanno una schifezza casuale al loro interno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.