Newsgroup: it.comp.programmare
Titolo: Memoria, Page e indirizzi Hex sui quali non mi trovo

Ciao a tutti.
Non riesco proprio a venirne fuori con gli indirizzi in esadecimale 
dell'output del programma MSD (Microsoft Diagnostic utility) 
raffigurante la mappatura della memoria.
Sappiamo che la memoria che va da 0 ad 1 MegaByte e' divisa in 64 pagine 
da 16KByte ciascuna (40 pagine da 0 a 640KByte) e sappiamo che si fa 
riferimento a queste pagine come "pagina 0", "pagina 1", "pagina 2", 
ecc., oppure si usano i loro indirizzi in esadecimale.
Ora, questo e' l'ouput del summenzionato programma:
------------------------------- Memory -----------------------------
Legend: Available "  "  RAM "##"  ROM "RR"  Possibly Available ".."
	EMS Page Frame "PP"  Used UMBs "UU"  Free UMBs "FF"
1024K FC00 RRRRRRRRRRRRRRRR FFFF  Conventional Memory
      F800 RRRRRRRRRRRRRRRR FBFF		 Total: 640K
      F400 RRRRRRRRRRRRRRRR F7FF	     Available: 625K
 960K F000 RRRRRRRRRRRRRRRR F3FF			640864 bytes
      EC00 FFFFFFFFFFFFFFFF EFFF
      E800 UUUUUUUUUUUUUUFF EBFF  Extended Memory
      E400 UUUUUUUUUUUUUUUU E7FF		 Total: 64512K
 896K E000 UUUUUUUUUUUUUUUU E3FF
      DC00 UUUUUUUUUUUUUUUU DFFF  MS-DOS Upper Memory Blocks
      D800 UUUUUUUUUUUUUUUU DBFF	    Total UMBs: 122K
      D400 PPPPPPPPPPPPPPPP D7FF       Total Free UMBs: 17K
 832K D000 PPPPPPPPPPPPPPPP D3FF    Largest Free Block: 17K
      CC00 PPPPPPPPPPPPPPPP CFFF
      C800 PPPPPPPPPPPPPPPP CBFF  Expanded Memory (EMS)
      C400 RRRRRRRRRRRRRRRR C7FF	   LIM Version: 4.00
 768K C000 RRRRRRRRRRRRRRRR C3FF    Page Frame Address: C800H
      BC00 ################ BFFF		 Total: 33152K
      B800 ################ BBFF	     Available: 32720K
      B400 UUUUUUUUUUUUUUUF B7FF
 704K B000 UUUUUUUUUUUUUUUU B3FF  XMS Information
      AC00                  AFFF	   XMS Version: 3.00
      A800                  ABFF	Driver Version: 3.5f
      A400                  A7FF      A20 Address Line: Enabled
 640K A000                  A3FF      High Memory Area: In use
					     Available: 65535K
				           Largest Free Block: 65535K
					    Available SXMS: 214976K
				           Largest Free SXMS: 214976K
				           VCPI Information
					    VCPI Detected: Yes
					       Version: 1.00
				           Available Memory: 32720K
-------------------------------------------------------------------------
Sappiamo che ogni riga di quello schema sono 16 KByte e che ogni 
elemento corrisponde ad 1 KB.
Se per esempio prendiamo la riga che va da B000 a B3FF (la riga che 
ha davanti il valore 704K), sappiamo che ogni "U" (a prescindere dal 
significato di U, spiegato poi nella legenda) occupa 1 KB.
Ecco, ora inizia il casino, perche' non mi trovo assolutamente con gli 
indirizzi in esadecimale che sono stati assegnati in quel grafico.
Se non erro B000 dovrebbe essere l'indirizzo della prima "U" di quella 
riga, mentre B3FF dovrebbe essere l'indirizzo dell'ultima U sempre della 
stessa riga.
Domanda: se B000 e' l'indirizzo al quale si trova la prima U (1 KB), 
qual'e' l'indirizzo al quale si trova la seconda U (e la terza, la 
quarta, ecc., fino alla penultima U)? Se considero uno spiazzamento di 
1024 byte (visto che ogni U occupa 1 KB) e se considero che ogni byte ha 
un proprio indirizzo, dovrebbe essere B400, ma se cosi' fosse tale 
valore sarebbe piu' grande dell'indirizzo dell'ultima U della riga, 
ovvero B3FF, dunque in conti non tornerebbero.
Si', so che sto sparando un oceano di cazzate, e' solo che non riesco 
proprio a trovarmi.
Qualche anima pia mi illuminerebbe per favore?
Ciao e grazie per le eventuali risposte.
Gigi_la_Trottola

 quarta, ecc., fino alla penultima U)?
B040, B080, B0C0, ...
il valore indicato a SX nell'output, e' il valore del segmento, per
ottenere l'indirizzo lineare lo devi moltiplicare per 16, viceversa da
indirizzo lineare vuoi il valore del segmento dividi per 16, quindi
1024byte lineari sono un incremento di 64 (40h) per il segmento.
ciao
donCiccio

 ovvero B3FF, dunque in conti non tornerebbero.
No, di nuovo. Un kilobyte - ovvero 0x400 bytes - in più di B0000
equivale - in termini lineari - a B0400, ovvero - in termini di
segmenti, come fa MSD - a B040.
Il secondo sarà a B080, il terzo a B0C0, il quarto a B100, e così via.
Saluti
Zello

 1024byte lineari sono un incremento di 64 (40h) per il segmento.
Finalmente ho capito, denghiu'. Avrei un dubbio pero', sempre in 
relazione all'output di MSD. Dagli appunti ho letto poi anche questo:
"Segments can start in memory every sixteen bytes, so the first segment 
(segment 0) starts at physical address 0, the second segment (segment 1) 
starts at physical address 16 dec (10 hex), the third segment (segment 2) 
starts at physical address 32 dec (20 hex), and so on. The last segment, 
segment 65535 dec (or FFFF hex), then has the physical address 1048560 
dec (FFFF0 hex). Note that the sixteen-byte difference between different 
segments is often called a paragraph. So, to get a physical address from 
a segment, we simply multiply the segment by 16 dec (10 hex). (Where does 
a segment end? Normally, we consider segments to be 64K in length, 
although this is not really specified anywhere. Often it is convenient to 
consider a particular segment to be shorter than 64K.)".
Ecco, viene detto che i segmenti possono partire di 16 byte in 16 byte, 
solo che noi invece consideriamo (come mi sembra faccia anche l'output di 
MSD) i segmenti che si trovano di 64K in 64K (per via del fatto che cosi' 
si sfruttano tutti i 16 bit dell'offset, che per l'appunto consentono di 
indirizzare 65536 bytes), e' giusto?
Se si' e riprendendo un attimo questo esempio,
 832K D000 PPPPPPPPPPPPPPPP D3FF
      CC00 PPPPPPPPPPPPPPPP CFFF
      C800 PPPPPPPPPPPPPPPP CBFF
      C400 RRRRRRRRRRRRRRRR C7FF
 768K C000 RRRRRRRRRRRRRRRR C3FF
      BC00 ################ BFFF
      B800 ################ BBFF
      B400 UUUUUUUUUUUUUUUF B7FF
 704K B000 UUUUUUUUUUUUUUUU B3FF
      AC00                  AFFF
      A800                  ABFF
      A400                  A7FF
 640K A000                  A3FF
allora tra il segmento B000 e il segmento C000, per esempio, dovrebbero 
starci 4096 segmenti, giusto?
Ancora, il segmento immediatamente successivo a B000 dovrebbe trovarsi a 
B010 (cioe' B000hex+10hex, ovvero 45056+16 in decimale), giusto?
Lo so, inizio a dare letteralmente i numeri, abbi pieta' per questa mia 
condizione (spero temporanea)  :)
Ciao e grazie per la pazienza  :)
Gigi_la_Trottola

cui si usa la tecnica seg+off per ottenere l'indirizzo lineare.
infatti, in modalità reale la memoria viene divisa in 65536 blocchi
da 16byte ciascuno.
cod

 B010 (cioe' B000hex+10hex, ovvero 45056+16 in decimale), giusto?
no, si trova a B001 cioe' 16 byte lineari distante.
per passare da seg:off a indirizzo lineare devi fare
lin = seg * 16 + off
gli indirizzi a 20 bit li devi rappresentare con 5 cifre esadecimali, il
fatto che MSD ne visualizzi solo 4 ti fa capire che sta visualizzando il
solo segmento, che occupa le 4 cifre piu' significative dell'indirizzo
lineare, cioe' B000 come segmento corrisponde a B0000 come indirizzo
lineare (vedi formula precedente).
ciao
donCiccio

 da 16byte ciascuno.
non e' vero, i blocchi sono da 64K, ma questo non vuol dire paginatura.
ciao
donCiccio

...
Allora, in modalità reale la memoria (fisica, non lineare, scusatemi
per il messaggio precedente - a forza di modalità protette e
paginazione...) è divisa in segmenti, ciascuno da 64 kb, che partono
ogni 16 byte
Morale:
segmento 0: va da 0 a 0x0ffff 
segmento 1: va da 0x10 a 0x1000f
segmento 2: va da 0x20 a 0x1001f
Ciò significa che i segmenti si sovrappongono, e che, per esempio, gli
indirizzi:
0000:0100
0001:00f0
0002:00e0
...
0010:0000
puntano al medesimo indirizzo fisico.
L'unica particolarità ce l'hanno i segmenti a partire dal F001, perché
sono in grado di generare indirizzi che sono oltre al megabyte di
indirizzamento in modalità reale.
Se si considera il segmento ffff, l'indirizzo:
ffff:ffff -> ffff0+ffff -> 10ffef
va ovviamente oltre al primo mega (indirizzo fisico 0xfffff, numero
massimo esprimibile con 20 bit)
Nell'8086 la cosa si risolveva "wrappando" gli ultimi segmenti, cioé
"ricominciando dall'indirizzo fisico 0": in altri termini, ffff:ffff
puntava all'indirizzo fisico ffef. Tutti i successivi processori Intel
partono - per compatibilità - comportandosi allo stesso modo, ma,
attivando il cosiddetto A20 gate si può fare in maniera da indirizzare
anche gli 0xffef byte oltre al muro dei megabyte. Se ti ricordi della
possibilità di caricare il dos in HMA, ciò che avveniva era proprio
questo: si attivava l'A20 gate e si sparava quanto più codice
residente del DOS possibile nei circa 64 kb oltre al primo megabyte
così ottenuti.
C'è da diventare scemi nel mondo segmento:offset, ma appena ti studi
un po' di modalità protetta, selettori e memoria lineare ti rendi
conto che fino a quà eravamo alle cose semplici....
Ciao,
Zello

 lineare (vedi formula precedente).
Faccio un po' fatica ma forse ho capito; per vedere se ho veramente 
capito mi tocca farti un'altra domanda  :)
Esempio: assumendo che B000 sia l'indirizzo del segmento 0 (e' un 
esempio), e' giusto dire che il byte 13 del segmento 3 ha indirizzo 
B003D?
Ciao e grazie ancora
Gigi_la_Trottola


direi di si, anche se mi puzza un po chiamarli segmento 0 e segmento
3.
il vero segmento 0 e' a indirizzo lineare 0, ed il vero segmento 3 e'
a indirizzo lineare 30h.
ciao
donCiccio

 3.
Si', sa di fetore anche a me, ma sul momento per fare l'esempio mi sono 
sembrati appropriati (perche' ero concentrato fissato su quella specifica 
riga che iniziava con segmento B000).
Grazie ancora di tutto, ho chiarito 'na bella tegola (per me che ho 
zero esperienza).
Ciao, Gigi_la_Trottola

anche gli 0xffef byte oltre al muro dei megabyte. Se ti ricordi della
   Piu` precisamente, c'era un "bug" nel 286, per cui, anche in
modalita` non protetta, non avveniva il wrap-around.
   L'8086 aveva un bus indirizzi a 20 bit, numerati da A0 (il meno
significativo) ad A19 (il piu` significativo). Il 286 aveva un bus
indirizzi a 24 bit (da A0 ad A23).
   Per esempio, l'indirizzo piu` alto esprimibile FFFF:FFFF,
corrisponde in teoria a 10FFEF, che in binario e`
100001111111111101111 (21 bit). E il 286 generava questo indirizzo a
21 bit, e non FFEF -> 1111111111101111 come l'8086.
   La IBM risolse il problema di compatibilita` introducendo il gate
A20, che inibiva il segnale emesso dal piedino A20 del 286, facendogli
generare indirizzi perfettamente compatibili con l'8086.
   Per passare in modalita` protetta, e poter utilizzare tutti i 16 MB
di ram, bisognava anche sbloccare il gate A20, per fare arrivare
nuovamente il segnale del piedino A20 del bus indirizzi al controller
di memoria.
   La Microsoft penso` bene di far sbloccare il gate A20 ad himem.sys,
per poter infilare un po' della parte residente di dos in quegli
indirizzi sopra il primo mega, e la cosa funziono` bene, perche`
pochissimi software funzionavano facendo affidamento sul wrap-around.
   Questo pero` costrinse l'Intel a far diventare il "bug" del 286 uno
standard (chi avrebbe voluto un 386 o un 486 senza la "High Memory
Area" - quei preziosissimi 64 KB? ;) ).
-- 
Totuccio.