Muistimalli x86 - alustoille on tapa määrittää oletukset , jotka kääntäjän on tehtävä luodessaan koodia alustoille , joissa on segmentoitu muistiosoite tai sivuttu muisti . Useimmiten termiä käytetään työskenneltäessä x86 -alustan erilaisten vanhojen tilojen kanssa .
Esimerkiksi 16-bittisellä x86 - yhteensopivalla alustalla on kuusi muistimallia. Ne määrittävät, mitä oletuksia tehdään oletusrekisterisegmentistä ja osoittimen koosta.
16-bittinen x86 - arkkitehtuuri mahdollistaa neljän segmenttirekisterin läsnäolon ansiosta samanaikaisen pääsyn neljään muistisegmenttiin. Segmenttirekisterien käyttötarkoitus:
Tällaisella alustalla on tapana kirjoittaa looginen osoite segmentillä : offset , jossa segmentti ja offset annetaan heksadesimaalimuodossa .
Reaalitilassa muistitavun fyysisen osoitteen laskemiseksi vastaavan segmenttirekisterin arvoa siirretään vasemmalle 4 bittiä ja sitten offset lisätään.
Esimerkiksi looginen osoite 7522:F139 antaa 20-bittisen fyysisen osoitteen:
75220 + F139 = 84359On huomattava, että tämä prosessi johtaa muistin aliasointiin , eli millä tahansa fyysisellä osoitteella voi olla useita loogisia esityksiä. Tämä tekee osoittimien vertailusta vaikeampaa.
Suojatussa tilassa GDT :tä ja LDT :tä käytetään samaan tarkoitukseen .
Osoittimet voivat olla tyyppiä lähellä (lähellä), kaukana (kaukana) tai suuria (iso).
Lähiosoitin viittaa nykyiseen segmenttiin, joten DS:n tai CS: n ei pitäisi muuttua, kun osoittimeen viitataan. Tämän tyyppiset osoittimet ovat nopeimpia, mutta rajoittuvat 64 kilotavun muistin osoitinalueeseen (eli nykyiseen segmenttiin).
Kauko - osoittimet sisältävät uuden DS- tai CS-arvon. Niiden käyttäminen edellyttää rekisterin vaihtamista, muistin viittausten poistamista ja sitten rekisterin palauttamista. Tällaiset osoittimet voivat osoittaa 1 megatavun muistiin. On huomattava, että aritmeettiset operaatiot osoittimilla (yhteen- ja vähennyslasku) eivät muuta osoittimen segmentin osaa, vaan vaikuttavat vain sen siirtymään. Nollan tai 65535:n (0xFFFF) ulkopuolella toimiville toiminnoille suoritetaan modulo 64K -toiminto, aivan kuten kaikki normaalit 16-bittiset toiminnot. Esimerkiksi signed −1 muuttuu allekirjoittamattomaksi 0xFFFF tai 65535.
Esimerkiksi seuraava koodi menee soveltamisalan ulkopuolelle ja korvaa itsensä:
char far * myfarptr = ( char far * ) 0x50000000L ; allekirjoittamaton pitkä laskuri ; for ( laskuri = 0 ; laskuri < 128 * 1024 ; laskuri ++ ) // käyttää 128K muistia * ( myfarptr + laskuri ) = 7 ; // kirjoita siihen kaikki seitsemänJossain vaiheessa laskuri on yhtä suuri kuin (0x10000), ja tuloksena oleva absoluuttinen osoite ylittää 0x5000:0000.
Valtavat osoittimet ovat pohjimmiltaan kaukaisia osoittimia, mutta ne normalisoidaan joka kerta, kun ne muuttuvat, jotta niillä on korkein segmentti, jonka ne voivat osoittaa. Tämä on melko hidasta, mutta se mahdollistaa osoittimen osoittamisen useisiin segmentteihin, ja se mahdollistaa myös tarkemman osoittimien vertailun, ikään kuin alusta olisi litteä muistimalli : tämä poistaa yllä mainitun muistin aliasoinnin käytöstä, joten kaksi suurta osoitinta osoittaminen yhteen ja samaan muistiin on aina yhtä suuri.
Muistimallit ovat:
Malli | Data | Koodi |
Pikkuruinen* | lähellä | |
pieni | kiinni** | lähellä |
Keskikokoinen | lähellä | kaukana |
Kompakti | kaukana | lähellä |
Suuri | kaukana | kaukana |
Valtava | valtava | valtava |
* Tiny-mallissa kaikki neljä segmenttirekisteriä osoittavat samaan segmenttiin.
** Kaikissa malleissa, joissa on lähellä dataosoittimia, SS on yhtä suuri kuin DS .
Suojatussa tilassa segmenttiä ei voi ylikirjoittaa, lukea tai suorittaa.
Siksi Small- ja Tiny-muistimalleja toteutettaessa koodisegmenttirekisterin on osoitettava samaan fyysiseen osoitteeseen ja sillä on oltava sama rajoitus kuin datasegmenttirekisterillä. Tämä eliminoi yhden 80286-prosessorin ominaisuuksista , joka varmistaa, että datasegmenttejä ei koskaan suoriteta ja koodisegmenttejä ei koskaan kirjoiteta päälle (mikä tarkoittaa, että itsemuovautuva koodi on kokonaan kielletty ). 80386-prosessoreissa , joissa on litteä muistimalli, on kuitenkin mahdollista kirjoittaa yksittäisiä muistisivuja.
Muistimallit eivät rajoitu 16-bittisiin ohjelmiin. Segmentointia on mahdollista käyttää myös 32-bittisessä suojatussa tilassa (jolloin saadaan 48-bittisiä osoittimia), ja sitä tukevat C- kääntäjät .
Segmentointi 32-bittisessä tilassa ei kuitenkaan salli pääsyä enempään osoiteavaruuteen kuin se, joka kattaa yhden segmentin, paitsi joitain segmenttejä, jotka eivät aina ole edustettuina muistissa, ja lineaarista osoiteavaruutta käytetään yksinkertaisesti välimuistina lisääntyneen osan vuoksi. segmentoitu virtuaalitila.
Suurimmaksi osaksi tämä mahdollistaa paremman suojan eri kohteiden pääsylle (enintään 1 megatavun kokoiset alueet voivat hyötyä tavu-tavulta jakamisesta, toisin kuin yksittäinen melko "karkea" 4 KiB:n jako). sivu), joten sitä käytetään vain erikoissovelluksissa, kuten tietoliikenneohjelmistoissa.
Teknisesti "tasainen" 32-bittinen osoiteavaruus on "pieni" muistimalli segmentoidulle osoiteavaruudelle. Molempien tekijöiden vaikutuksesta kaikki neljä segmenttirekisteriä sisältävät saman arvon.
x86-64 - alustalla on seitsemän muistimallia [1] , joissa useimmat symboliset linkit ovat vain 32-bittisiä ja jos osoite tiedetään linkin hetkellä (toisin kuin sijainnista riippumaton koodi ). Tämä ei vaikuta osoittimien käyttöön, jotka ovat aina tasaisia 64-bittisiä osoittimia, vaan ainoastaan arvon saannin kannalta merkkien allokoinnin kautta.