Hukommelsesmodellen for x86-platforme er en måde at specificere de antagelser, som compileren skal gøre, når den genererer kode til platforme med segmenteret hukommelsesadressering eller paged memory . Oftest bruges udtrykket, når man arbejder med forskellige ældre tilstande på x86 -platformen .
For eksempel er der seks hukommelsesmodeller på en 16-bit x86 - kompatibel platform. De bestemmer, hvilke antagelser der gøres om standardregistersegmentet og pointerstørrelsen.
16-bit x86 - arkitekturen tillader, på grund af tilstedeværelsen af fire segmentregistre, samtidig adgang til fire hukommelsessegmenter. Formål med segmentregistre:
På en sådan platform er det sædvanligt at skrive en logisk adresse som segment : offset , hvor segmentet og offset er angivet i hexadecimal notation .
I reel tilstand forskydes værdien af det tilsvarende segmentregister til venstre med 4 bit for at beregne den fysiske adresse for en hukommelsesbyte, og derefter tilføjes forskydningen.
For eksempel giver den logiske adresse 7522:F139 en 20-bit fysisk adresse:
75220 + F139 = 84359Det skal bemærkes, at denne proces resulterer i hukommelsesaliasing , det vil sige, at enhver given fysisk adresse kan have flere logiske repræsentationer. Dette gør sammenligning af pointer vanskeligere.
I beskyttet tilstand bruges GDT og LDT til samme formål .
Pointere kan være af typen nær (nær), langt (langt) eller enorm (stor).
Nærmarkøren refererer til det aktuelle segment, så hverken DS eller CS bør ændres, når markøren dereferences. Pointere af denne type er de hurtigste, men er begrænset til et markørområde på 64 kilobyte hukommelse (det vil sige det aktuelle segment).
Fjern pointers indeholder den nye DS- eller CS-værdi. For at bruge dem skal registret ændres, hukommelsen dereferences, og derefter skal registret gendannes. Sådanne pointere kan pege på 1 megabyte hukommelse. Det skal bemærkes, at aritmetiske operationer med pointere (addition og subtraktion) ikke ændrer sektionen af pointersegmentet, men kun påvirker dets offset. Operationer uden for nul eller 65535 (0xFFFF) vil blive udsat for en modulo 64K operation, ligesom enhver normal 16-bit operation. For eksempel bliver fortegn −1 usigneret 0xFFFF eller 65535.
For eksempel vil følgende kode gå uden for rækkevidde og overskrive sig selv:
char far * myfarptr = ( char far * ) 0x50000000L ; usigneret lang tæller ; for ( tæller = 0 ; tæller < 128 * 1024 ; tæller ++ ) // få adgang til 128K hukommelse * ( myfarptr + tæller ) = 7 ; // skriv alle syvere ind i denPå et tidspunkt vil tælleren blive lig med (0x10000), og den resulterende absolutte adresse vil overstige 0x5000:0000.
Kæmpe pointers er i det væsentlige langt pointere, men normaliseres hver gang de ændres, så de har det højeste segment, de kan adressere. Dette er ret langsomt, men det tillader en pointer at pege på flere segmenter, og det giver også mulighed for mere nøjagtig sammenligning af pointere, som om platformen var en flad hukommelsesmodel : dette deaktiverer hukommelsesaliasing som nævnt ovenfor, så to store pointere at pege på et og samme stykke hukommelse vil altid være ens.
Hukommelsesmodeller er:
Model | Data | Koden |
Lille bitte* | nær ved | |
lille | tæt** | nær ved |
Medium | nær ved | langt |
Kompakt | langt | nær ved |
stor | langt | langt |
Kæmpe stor | kæmpe stor | kæmpe stor |
* I Tiny-modellen peger alle fire segmentregistre på det samme segment.
** I alle modeller med nær-pegere til data er SS lig med DS .
I beskyttet tilstand kan segmentet ikke overskrives, læses eller udføres.
Derfor, når du implementerer Small og Tiny hukommelsesmodellerne, skal kodesegmentregistret pege på den samme fysiske adresse og have samme begrænsning som datasegmentregistret. Dette eliminerer en af funktionerne i 80286-processoren , som sikrer, at datasegmenter aldrig udføres, og kodesegmenter aldrig overskrives (hvilket betyder, at selvmodificerende kode er fuldstændig forbudt ). På 80386-processorer med dens flade hukommelsesmodel er det dog muligt at skrivebeskytte individuelle hukommelsessider.
Hukommelsesmodeller er ikke begrænset til 16-bit programmer. Det er også muligt at bruge segmentering i 32-bit beskyttet tilstand (hvilket resulterer i 48-bit pointere), og der er C-kompilere , der understøtter det.
Segmentering i 32-bit tilstand tillader dog ikke adgang til mere adresserum end det, der dækker ét segment, bortset fra nogle segmenter, der ikke altid er repræsenteret i hukommelsen, og det lineære adresserum bruges simpelthen som en cache på grund af den øgede segmenteret virtuelt rum.
For det meste giver dette bedre beskyttelse af adgang til forskellige objekter (områder op til 1 megabyte i størrelse kan drage fordel af byte-for-byte opdeling af adgangsbeskyttelse, i modsætning til den ret "grove" 4 KiB opdeling, der tilbydes af en enkelt side), og bruges derfor kun i specielle applikationer såsom telekommunikationssoftware.
Teknisk set er et "fladt" 32-bit adresserum en "lille" hukommelsesmodel for et segmenteret adresserum. Under påvirkning af begge faktorer indeholder alle fire segmentregistre den samme værdi.
På x86-64 -platformen er der syv hukommelsesmodeller [1] , hvor de fleste symbolske links kun er 32-bit, og hvis adressen er kendt på linktidspunktet (i modsætning til positionsuafhængig kode ). Dette påvirker ikke brugen af pointere, som altid er flade 64-bit pointere, men kun hvad angår værdiadgang via tegnallokering.