DOMANDA codice operativo e indirizzo operando

Pubblicità

sanvitomarina

Nuovo Utente
Messaggi
9
Reazioni
0
Punteggio
4
Ciao Ragazzi ho un problema nel capire la massima memoria indirizzabile. So che con 32 bit posso indirizzare al massimo 2^32 bytes, ma ho un dubbio... riporto quanto scritto su un libro.
"
L’insieme delle istruzioni riconosciute dal processore costituiscono l’instruction set del processore e
sono diretta conseguenza della sua architettura. Per chiarire questo aspetto consideriamo istruzioni
macchina con un solo indirizzo aventi il seguente formato, ipotizzando istruzioni che occupano una
parola di memoria di 32 bit:
8 bit per il codice Operativo e 24 bit per l'indirizzo operando.
L’istruzione è suddivisa in due campi di differente ampiezza per rappresentare: l’operazione da eseguire,
identificata da un codice operativo, e l’indirizzo di memoria di un operando coinvolto nell’istruzione.
Il set di istruzioni macchina e il formato stesso delle istruzioni riflettono l’architettura del processore
perché, per esempio, aver specificato che servono 8 bit per il codice operativo, significa che il set
di istruzioni macchina è composto da non più di 2 8 = 256 istruzioni.
Allo stesso modo si può dire che 24 bit per l’indirizzo dell’operando permettono di indirizzare una
memoria con al massimo 2 24 = 16×2 20 = 16 Mega parole di memoria. Questo fatto si esprime anche
dicendo che il processore permette di indirizzare uno spazio di memoria di 16M parole."
Quindi cosa vuol dire che posso indirizzare solo 2^24 bytes di memoria???
Grazie a tutti quelli che mi aiuteranno!!!
Marco
 
Quindi cosa vuol dire che posso indirizzare solo 2^24 bytes di memoria???
Grazie a tutti quelli che mi aiuteranno!!!
Marco

Esattamente questo. Un'istruzione può contenere un indirizzo in un range di 2^24. Questo non vuol dire che la macchina non possa usare indirizzi a 32 bit. Probabilmente gli indirizzi negli operandi sono tutti relativi, cioè indica di quanto ( in sù e/o in giù ) bisogna spostarsi rispetto all'istruzione corrente per trovare il dato specificato nell'operando.
 
ciao Andretti grazie della risposta, ma se avessi 32 bit come faccio a indirizzare 4 GB se ho sempre questo codice operativo che mi "ruba" dei bit a discapito dell'indirizzamento?
Grazie
Marco
--- i due messaggi sono stati uniti ---
Esattamente questo. Un'istruzione può contenere un indirizzo in un range di 2^24. Questo non vuol dire che la macchina non possa usare indirizzi a 32 bit. Probabilmente gli indirizzi negli operandi sono tutti relativi, cioè indica di quanto ( in sù e/o in giù ) bisogna spostarsi rispetto all'istruzione corrente per trovare il dato specificato nell'operando.
Ciao Pabloski grazie della risposta, potresti farmelo capire in modo più semplice? Non capisco cosa sono gli indirizzi relativi e il fatto di spostarsi più giù o più su.

Grazie Marco
 
Ultima modifica:
ciao Andretti grazie della risposta, ma se avessi 32 bit come faccio a indirizzare 4 GB se ho sempre questo codice operativo che mi "ruba" dei bit a discapito dell'indirizzamento?

La realtà è più complessa dell'esempio. ?

Considera ad esempio un'architettura che hai usato o che utilizzi ancora: x86. Questa è a 32bit e infatti esiste un limite massimo dato dalla quantità di memoria indirizzabile (2^32 = 4GB appunto). Questo è un limite fisico, imposto dall'hardware. Se hai 8GB di RAM, ne usi al massimo 4.
Il limite è dovuto al bus indirizzi e - se non sbaglio nome - al data bus.

Nella realtà l'istruzione è molto più grande di 32bit perchè sono presenti più campi. Considera che si arriva a istruzioni grandi anche 15bytes. Ci sono istruzioni che hanno uno operando che accede alla memoria (come nel tuo esempio) e in questi casi l'indirizzo specificato sarà a 32bit (4bytes).

Penso non ti torni la lunghezza per questo motivo: l'esempio che ti ha fatto il libro è solo per farti capire come funziona l'indirizzamento, ma nella realtà CPU a 32bit non significa istruzioni di 32bit, anzi (specie con architetture CISC, come Intel, dove le istruzioni hanno lunghezza variabile da 1 a 15 bytes).

Qualche anno fa scrissi Il linguaggio Macchina di 8086, se vuoi partire da qualcosa di relativamente semplice, puoi provare a leggerlo. La CPU in questo caso è a 16bit.

Poi ci sarebbe altro da dire, ma evito di aggiungere troppe informazioni per non farti fare confusione, a meno di tue domande specifiche.

Non capisco cosa sono gli indirizzi relativi e il fatto di spostarsi più giù o più su.
Penso faccia riferimento a istruzioni che invece di specificare direttamente un indirizzo vanno invece a specificare un valore, che viene sommato o sottratto all'indirizzo dell'istruzione corrente, dando quindi l'indirizzo finale.
 
Ciao Pabloski grazie della risposta, potresti farmelo capire in modo più semplice? Non capisco cosa sono gli indirizzi relativi e il fatto di spostarsi più giù o più su.

Grazie Marco

Credo che dando un'occhiata alla guida scritta da DispatchCode potrebbe esserti più chiaro.

In particolare, nel caso di x86, avendo limitazioni sull'ISA ( l'insieme delle istruzioni del processore ) usarono il trucco di introdurre i registri segmento. Grazie a quest'astuta trovata, riuscirono a far indirizzare indirizzi da 20 bit, usando un'architettura a 16 bit.

Il senso di quello che ho scritto è che:
  1. se limiti l'operando a 24 bit
  2. ovviamente non puoi farlo magicamente diventare 32 bit
  3. e quindi non puoi indirizzare a 32 bit
Quindi o aggiungi qualcosa da fuori, per esempio un registro segmento di cui usi 8 bit ( 24 + 8 = 32 ) per estendere l'indirizzo contenuto nell'operando o ti limiti ad usare quei 24 bit.

24 bit significa però 16 Mega! Dunque che fai? Limiti la memoria a 16 MB e chi ne ha di più non la usa? Sarebbe folle. L'unica altra soluzione ( a parte usare i registri segmento ) sarebbe di imporre che gli indirizzi espressi negli operandi sono in realtà degli spostamenti rispetto all'indirizzo dell'istruzione in cui sono contenuti.

Cioè, l'istruzione può trovarsi ovunque in quei 2^32 bytes, per cui puoi usare la tua memoria da 4 GB. Ma ogni istruzione del programma potrà, al massimo, puntare ad un dato ( o un'altra istruzione ) che si trovi a non più di 16 Mega da lei. E puoi ovviamente far sì che quello spostamento ( si chiama displacement in gergo ) sia un numero intero positivo ( cioè va da zero a 16 mega ) o relativo ( e va da -8 mega a +8 mega ).

Cioè, se il processore sta eseguendo l'istruzione che si trova all'indirizzo 1000 e il displacement è +30, vuol dire che l'operando punta alla locazione 1030.

Ovviamente c'è un inghippo. Ovvero l'impossibilità di esprimere indirizzi assoluti che coprono tutti i 32 bit. Cioè, il sistema non potrà mai allocare il tuo programma a partire da 40 Mega, questo perchè non ha un modo per esprimere quell'indirizzo. Ogni programma sarebbe limitato ad usare un'area di 16 Mega ( i 24 bit dell'operando ), ma il sistema operativo avrebbe bisogno di indirizzare tutto lo spazio ( 32 bit ) disponibile.

Per questa ragione c'è sempre bisogno di un metodo per esprimere indirizzi assoluti ( cioè che dicano al processore "vai a prendere il dato a questo indirizzo preciso" ) e questo metodo è la segmentazione.
 
grazie milleee a tutti e due già mi avete fatto capire tanto, avrei tante domande ma prima mi studio la guida e poi torno nel caso mi restano ancora dubbi.
Grazie davvero trovare persone disponibili ma soprattutto competenti non è semplice :)
a presto!
Marco
ps: la guida è disponibile anche in pdf?
 
Ultima modifica:
grazie milleee a tutti e due già mi avete fatto capire tanto, avrei tante domande ma prima mi studio la guida e poi torno nel caso mi restano ancora dubbi.
Grazie davvero trovare persone disponibili ma soprattutto competenti non è semplice :)
a presto!
Marco
ps: la guida è disponibile anche in pdf?
Di niente, lasciamo aperto il topic, in caso torna pure a domandare qui, se l'argomento è il medesimo.
Considera comunque che quella CPU è datata e al giorno d'oggi - ma già da una 30ina di anni fa - le cose sono un pò cambiate (8086 aveva un pò di limitazioni, come vedrai nell'articolo/guida).

No, in PDF non è disponibile, almeno per ora. ?
 
Ciao ragazzi ho letto già la prima parte e vorrei porvi due domande :)
La cpu 8086 è a 16 bit mentre il bus di indirizzi è a 20 bit.
Qui sotto scrivo le mie conclusioni, correggetemi se sbaglio :).
" la cpu riesce a indirizzare più dei di 2^16 in quanto crea degli spazi di memoria a 16 bit= 2^16 e poi riesce a indirizzare altri spazi di memoria partendo da quello e potendosi spostare ogni volta di un massimo di 2^20.
Così facendo "con questo trucchetto" sto aumentando la memoria che posso utilizzare"
La prima domanda è come faccio praticamente a spostarmi di 2^20 (quindi potrei passare dalla posizione 0 al massimo alla posizione 1048575) se la mia cpu può elaborare al massimo 65536 combinazioni.
la mia seconda domanda è perché nei sistemi a 32 bit il limite è 2^32 ovvero 4GB, non potrei utilizzare anche qui questo giochetto ?(con questo giochetto posso gestire una memoria infinita -.-')
Grazie,
Marco
 
Nel post precedente non ti ho suggerito sbadatamente una cosa: se le domande sono relative all'articolo/guida, sentiti libero di commentare li sotto. ?

La cpu 8086 è a 16 bit mentre il bus di indirizzi è a 20 bit.
Qui sotto scrivo le mie conclusioni, correggetemi se sbaglio :).
" la cpu riesce a indirizzare più dei di 2^16 in quanto crea degli spazi di memoria a 16 bit= 2^16 e poi riesce a indirizzare altri spazi di memoria partendo da quello e potendosi spostare ogni volta di un massimo di 2^20.
Così facendo "con questo trucchetto" sto aumentando la memoria che posso utilizzare"
La prima domanda è come faccio praticamente a spostarmi di 2^20 (quindi potrei passare dalla posizione 0 al massimo alla posizione 1048575) se la mia cpu può elaborare al massimo 65536 combinazioni.

Il "trucchetto" utilizzato dagli ingegneri è stato quello di utilizzare i segmenti. Ciascun segmento è grande 2^16. Questa componente viene memorizzata usando un registro di segmento, diciamo DS (Data Segment). Per "selezionare" un offset all'interno di questo segmento si usa un altro indirizzo, chiamato Offset. La coppia Segmento:Offset è un indirizzo composto da due registri a 16 bit.

Quello che avviene è la trasformazione di queseta coppia in un indirizzo lineare a 20bit: per farlo viene fatto lo shift di 4bit a sx e viene sommato l'offset. L'indirizzo finale che ottieni è quello al quale accedi.

Devi considerare che questa è in realtà una soluzione trovata a causa delle limitazioni imposte dall'hardware, e non grazie all'hardware.
Ciò che ha creato questo problema è il fatto di avere un address bus e un data bus di dimensioni differenti.

Tu non ti sposti di 2^20; tu hai 2^16 segmenti ciascuno grande 2^16bytes (per altro sono segmenti anche parzialmente sovrapposti). Non so se l'hai visto, ma c'è uno Spoiler nella prima parte, il contenuto è importante in quanto va proprio a chiarire questi aspetti, lo riporto integralmente qui:

(chiedo venia, ma trattandosi di una risposta data in un post, troverete magari riferimenti ad un singolo)

Sotto 8086 la memoria è divisa in segmenti: ciascun segmento è grande 65536byte. Per spostarsi all'interno di un segmento si usa un Offset (spiazzamento, sarebbe il termine corretto). Ecco che nasce quindi la coppia Segmento:Offset.
In pratica, il segmento 0 ha 65536byte, il segmento 1 ha 65536byte... il segmento 65536 ha 65536byte. Questa rappresentazione era necessaria in quanto a quell'epoca si utilizzavano appunto i segmenti (infatti era un disastro quando un programma cresceva di dimensioni); ogni segmento è di 64KB, appunto.
Con 65536 segmenti e 65536 spiazzamenti, puoi indirizzare 2^32 byte di memoria (questo perchè sia i segmenti sia gli offset/spiazzamenti sono a 16bit, quindi 2^16 * 2^16=2^32). Detto così sembra poco, ma in realtà si tratta di 4294967296byte, ovvero 4GB.

Ora la situazione si fa contorta: come diceva anche Madda, l'indirizzo fisico è espresso a 20bit, ma quello logico soltanto a 16. Questo perchè l'architettura dell'8086 era a 16bit; il problema è che il bus degli indirizzi (l'address bus) è a 20bit. 20bit significa 2^20, ovvero 1MB di memoria. In pratica poteva indirizzare 1MB di memoria (ma grazie all'idea dei progettisti spiegata li sopra, divennero ben 4GB).

La coppia logica è formatta come dicevo prima da Segmento:Offset, ciascuno di 16bit. Ciascun segmento di memoria parte inoltre da un indirizzo fisico che è un multiplo di 16, chiamato paragrafo.
Abbiamo alcune "costanti" numeriche da ricordare. 65536 in esadecimale si scrive FFFFh, e sono appunto 16bit. Se utilizziamo 20bit per rappresentarlo, scriveremo 0FFFFh. Il fatto che ciascun paragrafo si trovi ad un multiplo di 16 permette una conversione abbastanza rapida e semplice da una coppia logica (Segmento:Offset) in una fisica.

Vogliamo sapere l'indirizzo fisico (quindi nella RAM) di questa coppia: 1234h:0005h. Qui abbiamo quindi come segmento 1234h, e come Offset 0005h. La conversione in indirizzo fisico avviene come descritto da Madda (16 in esadecimale corrisponde a 10h):


Codice:
(segmento * 10h) + Offset

(1234h * 10h) + 0005h = 12340h + 0005h = 12345h

L'indirizzo fisico corrispondente è quindi 12345h (che come noti è a 20bit). Al posto di moltiplicare per 16, si può utilizzare lo shift a sinistra. Ogni spostamento a sinistra equivale ad una moltiplicazione per 2 del numero. Spostare 4bit a sinistra, significa quindi moltiplicare per 16. Si usa lo shift in quanto è più veloce di una moltiplicazione (in realtà il chip includeva un circuito speciale dedicato a questo tipo di conversione).

La conversione da fisico a logico risulta altrettanto semplice. Si può prendere come esempio l'indirizzo ottenuto nell'esempio qui sopra, 12345h. Per ottenere Segmento:Offset si considerano i bit di livello più alto, sino a contarne 16; gli altri rimanenti rappresentano l'offset. Per farla semplice: se hai l'indirizzo espresso in esadecimale, i primi 4 bit a sinistra rappresentano l'indirizzo logico, quindi:

Codice:
12345h -> 1234h:0005h


Vi sono alcune osservazioni molto importanti da fare ora: se vi è stata spiegato l'indirizzamento lineare, saprai che esiste una corrispondenza biunivoca tra l'indirizzo lineare e l'indirizzo fisico, ovvero: un indirizzo lineare corrisponde ad un indirizzo fisico. Purtroppo con la coppia logica la situazione non è più la stessa in quanto i segmenti sono parzialmente sovrapposti.
Cosa significa in pratica? Per capire, osserva sempre la coppia logica dell'esempio precedente. L'indirizzo fisico risultante è: 12345h. Ma esistono altri modi per ottenerlo:


Codice:
1234h:0005h
1233h:0015h
1232h:0025h
1231h:0035h
1230h:0045h
122Fh:0055h
122Eh:0065h
122Dh:0075h
.................
.................
0235h:FFF5h

Te ne ho mostrati solo alcuni (e l'ultimo). Qualche anno fa scrissi due righe in Java per convertire indirizzi logici in indirizzi fisici e viceversa. Se lo trovo lo posto, o scrivo due righe in C/C++ o altro e posto l'exe, che magari è più utile.

Come noti comunque, tutte quelle coppie logiche daranno come risultato lo stesso indirizzo fisico.

L'altro aspetto da considerare è che gli ultimi segmenti hanno meno di 65536byte. Qual è l'ultima coppia logica che genera l'ultimo indirizzo fisico? Questa:

Codice:
FFFFh:000Fh

(FFFFh * 10h) + 000Fh = FFFFFh

Come noti è l'ultimo. Questo significa che dell'ultimo segmento sono usati solo 16byte. Il segmento prima invece avrà solo 32byte... e così via a ritroso.

Come dico sotto spoiler era una risposta data tanti anni fa in un topic (eh, penso 10 o 12 anni fa), quindi non far caso a qualche nick che ogni tanto cito.

Inoltre, detto tutto ciò, devi considerare anche che la CPU 8086 operava in modalità reale, e che solo più avanti è stata introdotta la modalità protetta.
In modalità reale potevi praticamente fare qualsiasi cosa, non c'erano controlli di sicurezza, e gli indirizzi che specificavi erano "fisici" e non virtuali, come ora (con "ora" intendo sempre da 30 anni fa ad adesso).

la mia seconda domanda è perché nei sistemi a 32 bit il limite è 2^32 ovvero 4GB, non potrei utilizzare anche qui questo giochetto ?(con questo giochetto posso gestire una memoria infinita -.-')

Da 80286 (se non vado errato, non vorrei sbagliare) è presente la modalità protetta. Da 80386 le cose sono poi migliorate notevolmente: questa CPU è a 32bit. Qui era appunto presente la modalità protetta dove possono coesistere più programmi in memoria (RAM) e non è necessario "spostare" il primo sul disco per mantenere il secondo; cosa molto importante, la modalità protetta consente anche di evitare che un programma invada lo spazio in memoria di un altro programma.

Qui (da 80386) è avvenuta una cosa molto importante: l'introduzione della paginazione. Ogni programma ha inoltre uno spazio di indirizzamento virtuale. La paginazione consente di caricare solo parti del programma in memoria, e anche all'occorrenza di effettuare lo swap su disco.

In merito alla memoria virtuale e rispondendo alla tua domanda: attualmente in esecuzione ci sono molteplici programmi, ciascuno con un proprio spazio in memoria e ciascuno con un proprio spazio di indirizzamento virtuale. Sopra dicevo che ora le cose ora sono diverse... e in effetti lo sono, e molto: l'indirizzo - faccio un esempio - 0x004000 del programma A non accede alla stessa posizione in RAM del medesimo indirizzo se è il programma B a specificarlo.
Questo perchè quegli indirizzi sono identici, ma hanno una base di partenza diversa al momento della traduzione: in pratica quell'indirizzo viene tradotto da virtuale - quello che vedi li sopra scritto - in quello fisico, che è la posizione in memoria (RAM). La base di partenza della traduzione è diversa, inizia da due indirizzi diversi.

Per non essere troppo astratto riporto l'immagine presa da un mio articolo:

vm_translation-png.384542


In questo caso è un 64bit, ma il concetto è il medesimo del 32bit.
Ogni programma mantiene un proprio indirizzo univoco, che è appunto come dicevo sopra la base di partenza di questa traduzione; quando la CPU decide di eseguirlo, questo indirizzo viene spostato in un registro della CPU chiamato CR3.
Da lì si prende la tabella di partenza, e usando alcuni bit dell'indirizzo virtuale al quale si sta accedendo, si va alla tabella successiva.

Ho cercato di non complicare troppo le cose, ma trattandosi di argomenti complessi, spero di non aver fatto troppa confusione. Ho parlato di questo argomento in un altro articolo (dal quale ho preso l'immagine), ma ti consiglierei prima di terminare almeno il precedente e di familiarizzare con paginazione, segmentazione e memoria virtuale prima di leggerlo.
Qui illustro come avviene la conversione di un indirizzo virtuale in uno fisico https://forum.tomshw.it/threads/articolo-memoria-virtuale-x64-virtual-address-translation.830716/
Se vuoi leggerlo adesso, ti consiglierei di fermarti alla lettura del paragrafo "La Paginazione".

Spero di non aver complicato troppo le cose... comunque il consiglio spassionato è di leggerti un paio di testi (sempre se non stai già studiando a scuola/uni): architettura dei calcolatori e sistemi operativi.
Non scendono mai in troppi dettagli implementativi, ma ti danno ottime basi per mettere poi assieme le cose e approfondire quello che vuoi approfondire.
Puoi iniziare anche a dare un occhio a Wiki https://en.wikipedia.org/wiki/Memory_paging
 
Nel post precedente non ti ho suggerito sbadatamente una cosa: se le domande sono relative all'articolo/guida, sentiti libero di commentare li sotto. ?



Il "trucchetto" utilizzato dagli ingegneri è stato quello di utilizzare i segmenti. Ciascun segmento è grande 2^16. Questa componente viene memorizzata usando un registro di segmento, diciamo DS (Data Segment). Per "selezionare" un offset all'interno di questo segmento si usa un altro indirizzo, chiamato Offset. La coppia Segmento:Offset è un indirizzo composto da due registri a 16 bit.

Quello che avviene è la trasformazione di queseta coppia in un indirizzo lineare a 20bit: per farlo viene fatto lo shift di 4bit a sx e viene sommato l'offset. L'indirizzo finale che ottieni è quello al quale accedi.

Devi considerare che questa è in realtà una soluzione trovata a causa delle limitazioni imposte dall'hardware, e non grazie all'hardware.
Ciò che ha creato questo problema è il fatto di avere un address bus e un data bus di dimensioni differenti.

Tu non ti sposti di 2^20; tu hai 2^16 segmenti ciascuno grande 2^16bytes (per altro sono segmenti anche parzialmente sovrapposti). Non so se l'hai visto, ma c'è uno Spoiler nella prima parte, il contenuto è importante in quanto va proprio a chiarire questi aspetti, lo riporto integralmente qui:



Come dico sotto spoiler era una risposta data tanti anni fa in un topic (eh, penso 10 o 12 anni fa), quindi non far caso a qualche nick che ogni tanto cito.

Inoltre, detto tutto ciò, devi considerare anche che la CPU 8086 operava in modalità reale, e che solo più avanti è stata introdotta la modalità protetta.
In modalità reale potevi praticamente fare qualsiasi cosa, non c'erano controlli di sicurezza, e gli indirizzi che specificavi erano "fisici" e non virtuali, come ora (con "ora" intendo sempre da 30 anni fa ad adesso).



Da 80286 (se non vado errato, non vorrei sbagliare) è presente la modalità protetta. Da 80386 le cose sono poi migliorate notevolmente: questa CPU è a 32bit. Qui era appunto presente la modalità protetta dove possono coesistere più programmi in memoria (RAM) e non è necessario "spostare" il primo sul disco per mantenere il secondo; cosa molto importante, la modalità protetta consente anche di evitare che un programma invada lo spazio in memoria di un altro programma.

Qui (da 80386) è avvenuta una cosa molto importante: l'introduzione della paginazione. Ogni programma ha inoltre uno spazio di indirizzamento virtuale. La paginazione consente di caricare solo parti del programma in memoria, e anche all'occorrenza di effettuare lo swap su disco.

In merito alla memoria virtuale e rispondendo alla tua domanda: attualmente in esecuzione ci sono molteplici programmi, ciascuno con un proprio spazio in memoria e ciascuno con un proprio spazio di indirizzamento virtuale. Sopra dicevo che ora le cose ora sono diverse... e in effetti lo sono, e molto: l'indirizzo - faccio un esempio - 0x004000 del programma A non accede alla stessa posizione in RAM del medesimo indirizzo se è il programma B a specificarlo.
Questo perchè quegli indirizzi sono identici, ma hanno una base di partenza diversa al momento della traduzione: in pratica quell'indirizzo viene tradotto da virtuale - quello che vedi li sopra scritto - in quello fisico, che è la posizione in memoria (RAM). La base di partenza della traduzione è diversa, inizia da due indirizzi diversi.

Per non essere troppo astratto riporto l'immagine presa da un mio articolo:

vm_translation-png.384542


In questo caso è un 64bit, ma il concetto è il medesimo del 32bit.
Ogni programma mantiene un proprio indirizzo univoco, che è appunto come dicevo sopra la base di partenza di questa traduzione; quando la CPU decide di eseguirlo, questo indirizzo viene spostato in un registro della CPU chiamato CR3.
Da lì si prende la tabella di partenza, e usando alcuni bit dell'indirizzo virtuale al quale si sta accedendo, si va alla tabella successiva.

Ho cercato di non complicare troppo le cose, ma trattandosi di argomenti complessi, spero di non aver fatto troppa confusione. Ho parlato di questo argomento in un altro articolo (dal quale ho preso l'immagine), ma ti consiglierei prima di terminare almeno il precedente e di familiarizzare con paginazione, segmentazione e memoria virtuale prima di leggerlo.
Qui illustro come avviene la conversione di un indirizzo virtuale in uno fisico https://forum.tomshw.it/threads/articolo-memoria-virtuale-x64-virtual-address-translation.830716/
Se vuoi leggerlo adesso, ti consiglierei di fermarti alla lettura del paragrafo "La Paginazione".

Spero di non aver complicato troppo le cose... comunque il consiglio spassionato è di leggerti un paio di testi (sempre se non stai già studiando a scuola/uni): architettura dei calcolatori e sistemi operativi.
Non scendono mai in troppi dettagli implementativi, ma ti danno ottime basi per mettere poi assieme le cose e approfondire quello che vuoi approfondire.
Puoi iniziare anche a dare un occhio a Wiki https://en.wikipedia.org/wiki/Memory_paging
grazie mille per la tua disponibilità.
Non ho capito tutto quello che hai scritto, ora finisco a leggere il tuo articolo e poi mi studio paginazione, segmentazione e memoria virtuale.
Puoi consigliarmi dei testi da studiare?
Inoltre perché con 32 bit il massimo è 4Gb di indirizzamento, non si può applicare il metodo fatto nella cpu 8086? ovvero che anche avendo 16 bit si riesce a indirizzare fino a 4 GB?
Marco
 
Inoltre perché con 32 bit il massimo è 4Gb di indirizzamento, non si può applicare il metodo fatto nella cpu 8086? ovvero che anche avendo 16 bit si riesce a indirizzare fino a 4 GB?
Marco

2^32 = 4 Giga, è semplicemente questa la ragione

il perchè non si può andare oltre nemmeno coi segmenti, è che il bus indirizzi fisico è 32 bit...i segmenti sono un artificio software, ma non puoi usarli per far comparire dei fili sul bus fisico e quindi estenderlo

e no, la cpu a 16 bit della famiglia x86 non indirizzare 4 Giga

quello che avvenne è che il bus indirizzi dell'8086 ( rispetto all'8088 ) fu esteso a 20 bit...solo che le istruzioni che operavano su indirizzi ammettevano solo operandi di tipo indirizzi al massimo di 16 bit

e questo per una questione di compatibilità col predecessore 8088

il trucco che inventarono fu appunto di usare i segmenti per aggiungere quei 4 bit in piu' necessari ad arrivare a 20 bit

e se vai a guardare all'80286, noterai che il bus indirizzi fu esteso a 24 bit e si continuarono ad usare i segmenti

tuttavia non farti fregare, perchè 80286 accedeva a tutti i 24 bit solo in modalità protetta...e in modalità protetta i registri segmento diventano selettori di segmento, cioè contenevano un indice a 16 bit che puntava ad un'entry in una tabella ( simile alle moderne tabelle delle pagine, ma piu' semplice ) che conteneva un'indirizzo a 24 bit che era la base a cui sommare l'offset per produrre l'indirizzo finale

col passaggio al 386 e ai 32 bit, i segmenti sono rimasti per compatibilità, ma tutti i sistemi operativi li pongono a zero...cioè non sono usati, questo perchè i registri generali sono a 32 bit e non c'è bisogno di nessun trucco per indirizzare i 2^32 bytes disponibili

col passaggio alla modalità x64, i segmenti sono proprio stati deprecati e, infatti, in long mode il processore non li usa affatto
 
grazie mille per la tua disponibilità.
Non ho capito tutto quello che hai scritto, ora finisco a leggere il tuo articolo e poi mi studio paginazione, segmentazione e memoria virtuale.
Puoi consigliarmi dei testi da studiare?
Inoltre perché con 32 bit il massimo è 4Gb di indirizzamento, non si può applicare il metodo fatto nella cpu 8086? ovvero che anche avendo 16 bit si riesce a indirizzare fino a 4 GB?
Marco

Ha risposto praticamente a tutto pabloski.
Aggiungo solo una cosa, integrando una info: pabloski fa riferimento ad altre tabelle, se ti interessa, si chiamano GDT (Global Descriptor Table) e LDT (Local Descriptor Table).
Poi mi sembra futile andare a puntualizzare alcune cose, poichè rischiamo solo di aggiungere troppo materiale senza riuscire nemmeno ad essere sufficientemente esaustivi.

In merito ai libri ti potrei suggerire due testi di due autori differenti sui sistemi operativi:
- Sistemi operativi. Concetti ed esempi
- I moderni sistemi operativi

Il primo è un ottimo testo; il secondo idem, ed è di un autore molto conosciuto (Tanebaum). Mi sentirei comunque di suggerirti il primo.
Del secondo autore trovi anche "architettura dei calcolatori".
Questi sono solo un antipasto. Poi se ti interesserà approfondire ulteriormente dovrai guardare altri testi, o letture più specifiche (ad esempio relative a Linux o a FreeBSD o a Windows, anche se è un pò più complicato trovare molto materiale, essendo closed source, fatta eccezione per "Windows Internals").

Come ulteriore risorsa c'è l'ottimo https://wiki.osdev.org/Main_Page
Qui puoi approfondire svariati aspetti.

Se vuoi provare del dolore fisico (?) c'è il manuale per gli sviluppatori di Intel: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
La versione che comprende tutti i volumi penso si aggiri sulle 5.000 pagine e oltre, attualmente.
 
2^32 = 4 Giga, è semplicemente questa la ragione

il perchè non si può andare oltre nemmeno coi segmenti, è che il bus indirizzi fisico è 32 bit...i segmenti sono un artificio software, ma non puoi usarli per far comparire dei fili sul bus fisico e quindi estenderlo

e no, la cpu a 16 bit della famiglia x86 non indirizzare 4 Giga

quello che avvenne è che il bus indirizzi dell'8086 ( rispetto all'8088 ) fu esteso a 20 bit...solo che le istruzioni che operavano su indirizzi ammettevano solo operandi di tipo indirizzi al massimo di 16 bit

e questo per una questione di compatibilità col predecessore 8088

il trucco che inventarono fu appunto di usare i segmenti per aggiungere quei 4 bit in piu' necessari ad arrivare a 20 bit

e se vai a guardare all'80286, noterai che il bus indirizzi fu esteso a 24 bit e si continuarono ad usare i segmenti

tuttavia non farti fregare, perchè 80286 accedeva a tutti i 24 bit solo in modalità protetta...e in modalità protetta i registri segmento diventano selettori di segmento, cioè contenevano un indice a 16 bit che puntava ad un'entry in una tabella ( simile alle moderne tabelle delle pagine, ma piu' semplice ) che conteneva un'indirizzo a 24 bit che era la base a cui sommare l'offset per produrre l'indirizzo finale

col passaggio al 386 e ai 32 bit, i segmenti sono rimasti per compatibilità, ma tutti i sistemi operativi li pongono a zero...cioè non sono usati, questo perchè i registri generali sono a 32 bit e non c'è bisogno di nessun trucco per indirizzare i 2^32 bytes disponibili

col passaggio alla modalità x64, i segmenti sono proprio stati deprecati e, infatti, in long mode il processore non li usa affatto
sono un po confuso... nello spolier ho letto questo:
"Ora la situazione si fa contorta: come diceva anche Madda, l'indirizzo fisico è espresso a 20bit, ma quello logico soltanto a 16. Questo perché l'architettura dell'8086 era a 16bit; il problema è che il bus degli indirizzi (l'address bus) è a 20bit. 20bit significa 2^20, ovvero 1MB di memoria. In pratica poteva indirizzare 1MB di memoria (ma grazie all'idea dei progettisti spiegata li sopra, divennero ben 4GB)."
cioè non capisco se nel 8086 con 20 bit riesco a gestire 4GB perché con 32 bit non potrei fare la stessa cosa e quindi superare i 4 GB?
--- i due messaggi sono stati uniti ---
Ha risposto praticamente a tutto pabloski.
Aggiungo solo una cosa, integrando una info: pabloski fa riferimento ad altre tabelle, se ti interessa, si chiamano GDT (Global Descriptor Table) e LDT (Local Descriptor Table).
Poi mi sembra futile andare a puntualizzare alcune cose, poichè rischiamo solo di aggiungere troppo materiale senza riuscire nemmeno ad essere sufficientemente esaustivi.

In merito ai libri ti potrei suggerire due testi di due autori differenti sui sistemi operativi:
- Sistemi operativi. Concetti ed esempi
- I moderni sistemi operativi

Il primo è un ottimo testo; il secondo idem, ed è di un autore molto conosciuto (Tanebaum). Mi sentirei comunque di suggerirti il primo.
Del secondo autore trovi anche "architettura dei calcolatori".
Questi sono solo un antipasto. Poi se ti interesserà approfondire ulteriormente dovrai guardare altri testi, o letture più specifiche (ad esempio relative a Linux o a FreeBSD o a Windows, anche se è un pò più complicato trovare molto materiale, essendo closed source, fatta eccezione per "Windows Internals").

Come ulteriore risorsa c'è l'ottimo https://wiki.osdev.org/Main_Page
Qui puoi approfondire svariati aspetti.

Se vuoi provare del dolore fisico (?) c'è il manuale per gli sviluppatori di Intel: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
La versione che comprende tutti i volumi penso si aggiri sulle 5.000 pagine e oltre, attualmente.
Perfetto inizio con il primo!
Marco
 
sono un po confuso... nello spolier ho letto questo:
"Ora la situazione si fa contorta: come diceva anche Madda, l'indirizzo fisico è espresso a 20bit, ma quello logico soltanto a 16. Questo perché l'architettura dell'8086 era a 16bit; il problema è che il bus degli indirizzi (l'address bus) è a 20bit. 20bit significa 2^20, ovvero 1MB di memoria. In pratica poteva indirizzare 1MB di memoria (ma grazie all'idea dei progettisti spiegata li sopra, divennero ben 4GB)."
cioè non capisco se nel 8086 con 20 bit riesco a gestire 4GB perché con 32 bit non potrei fare la stessa cosa e quindi superare i 4 GB?

2^16 * 2^16 = 2^32. Ma è solo nella teoria, nel senso che il bus rimane a 20bit con 8086. La coppia logica viene per forza di cose trasformata nell'indirizzo a 20bit (segmento * 16 + offset, è ottieni l'indirizzo 20bit).
Quindi al massimo supporta 1MB.

Con un 32bit hai il bus a 32bit, quindi al massimo indirizzi 32bit di memoria, ovvero 4GB (appunto il max che vedi con un 32bit).

Qualsiasi altra astrazione ti inventi sopra non cambia quello che c'è sotto al cofano, perché quello è fisico.
 
Pubblicità
Pubblicità
Indietro
Top