Memóriakezelés I. ÕA memória címzése; ÕA memória felosztása; ÕAbszolút változó (rádefiniálás); ÕMemóriatömbök.
Készítette: dr. Nyári Tibor
A memória címzése: Emlékeztető!
A memóriát byte-onként címezzük,
a címzéshez regiszter-eket használunk.
16 bit-es címzési mód: 1 regiszter=2 byte(=16 bit)
216(=65535 byte) 64 Kbyte címezhető meg.
32 bit-es címzési mód: 232 byte 4096 Mbyte címezhető meg.
Alapfogalmak: Abszolút cím: a memória valamely byte-jának a memória elejétől számított fizikai címe Relatív cím: a memória valamely pontjától számított cím Paragrafus: a memória egy 16 byte nagyságú része (a paragrafus mindig egy 16-tal osztható fizikai címen kezdődik, így a „k.” paragrafus a „k*16.” byte-on kezdődik)
Szegmens: egy vagy több paragrafusból álló folytonos memóriaterület (nagysága nem haladhatja meg a 64 Kbyte-ot, a kezdőcíme megadható paragrafusokban vagy abszolút módon)
Paragrafusokban általában egy szegmens kezdetét szokás megadni szegmenscím
Például: Egy 3 paragrafusnyi, 48 byte méretű szegmens, amelynek szegmenscíme: 2 0 16 byte
$0010 (16)
1 16 byte
$0020 (32)
2 16 byte
$0030 (48)
3 16 byte
$0040 (64)
4 16 byte
16 byte
szegmenscím
abszolút cím
$0000 (0)
DOS
Kétkomponensű címzési módszer
Egy fizikai címet egy szegmenscím és egy ofszetcím határoz meg. Szegmens:Ofszet Szegmenscím: egy szegmens címe paragrafusokban Ofszetcím: a szegmensen belüli relatív cím
eltolás
- mindkét cím egy-egy regiszter, értéke: $0000 - $FFFF - több Szegmens:Ofszet is meghatározhat egy memóriacímet Normált cím: ha az eltolás értéke 0 - 15 közé esik - normált cím esetén egy címet csak egyféleképpen lehet megadni
Például: Ha a szegmenscímet megszorozzuk 16-tal, és hozzáadjuk az ofszetcímet, akkor megkapjuk, hogy a fizikai cím a memória hányadik byte-ja. byte $0001:$0021
1 * 16 + 33 = 49
$0002:$0011
2 * 16 + 17 = 49
$0003:$0001
3 * 16 + 1 = 49
mindhárom cím ugyanazt a byte-ot határozza meg a memória 49. ($0031.) byte-ját. az 1 Mbyte teteje: $FFFF:$000F, azaz 65535 * 16 + 15 = 1 048 575
A memória felosztása: $10000:$0000
$E000:$0000 $C000:$0000 $A000:$0000
AT extended memória ROM BIOS terület Installálható ROM terület Video pufferek területe DOS átmeneti része Átmeneti programterület Transient Program Area DOS rezidens része
$0040:$0000 $0000:$0000
ROM BIOS adatterület Megszakítási vektortábla
Címek
A megszakítási vektortáblában a hardware és a software megszakítások címei vannak.
A megszakítási rutinok olyan végrehajtható eljárások, melyeket a rendszer használ anélkül, hogy sok esetben a programozó tudna róla.
A vektortábla rutinjait a programozó is felhasználhatja saját céljaira.
Megszakítási vektortábla
Rendszerterület, amely a hardware vezérléséhez szükséges adatokat tartalmazza.
Ezt a területet átírni csak a rendszer alapos ismerete esetén szabad!
ROM BIOS adatterület
A DOS alaprutinjai, alaprutinjai amelyek indításkor betöltődnek a memóriába és az operációs rendszer futása során ott is maradnak.
DOS rezidens része
Ez a terület a 640 kbyte legnagyobb része, ide kerülnek a felhasználói programok.
Ide kerül az általunk írt program is, ezért ennek elhelyezkedését a memóriában és a program által használt további memóriaterületeket részletesen tárgyaljuk.
Átmeneti programterület Transient Program Area
Értelemszerűen az operációs rendszer átmenetileg használt részeinek területe.
DOS átmeneti része
Képernyőmemóriák területe.
A rendszer egy képernyőmemória tartalmát vetíti ki a monitorra.
Más-más típusú videokártyák esetén a videopuffer ezen területen belül különböző címeken helyezkedhet el.
Video pufferek területe
Ezt a területet a rendszer foglalja magának.
Installálható ROM terület
Ezt a területet a rendszer foglalja magának.
ROM BIOS terület
AT extended memória Extended (bővített) memória: - az 1Mbyte feletti memória rész, sz melyet a processzor csak védett üzemmódban tud elérni.
A *.exe állomány elhelyezkedése a tárban:
HeapEnd HeapPtr
HeapOrg
Szabad memória
Heap
OvrHeapEnd
Overlay puffer Verem Sseg:SPtr SSeg:$0000
OvrHeapOrg
Szabad verem Globális változók Típusos állandók System egység kódszegmens 1. egység kódszegmens
Átmeneti programterület
2. egység kódszegmens
Transient Program Area
CSeg:$0000 k. egység kódszegmens Főprogram kódszegmens PrefixSeg
PSP
*.exe tartalma
DSeg:$0000
PS P: Program Segment Prefix
Egy 256 byte-os memóriaterület, melyet az operációs rendszer állít elő az „*.exe” állomány betöltésekor.
A PSP szegmenscímét a System egység PrefixSeg változója tartalmazza.
PrefixSeg
PSP
A kódszegmens: A program jól elkülöníthető programrészekből szek áll. Egy Pascal programnak mindig van egy főprogramja, program amely különböző modulokat modulok használ. Ezek lehetnek szabványos modulok (System, Crt, Printer, stb.) és a programozó által készített, tett majd a programhoz hozzászerkesztett modulok. modul Minden modul lefordított kódja egy külön szegmens, szegmens melyek egymás után helyezkednek el a tárban:
Egy kódszegmens maximális mérete: 64 kbyte CSeg:$0000 A program futásakor a vezérlés mindig más kódszegmensben van, az aktuális szegmens szegmenscímét a processzor CS (CodeSegment) regisztere tartalmazza, melynek értékét a SYSTEM egység Cseg függvényével lekérdezhetjük. ny
Típusos állandók System egység kódszegmens 1. egység kódszegmens 2. egység kódszegmens
k. egység kódszegmens Főprogram kódszegmens
*.exe tartalma
DSeg:$0000 - főprogram kódszegmense; - programhoz szerkesztett modulok kódszegmensei fordított sorrendben, sorrendben mint ahogyan azokat a USES kulcsszó után megadtuk, majd pedig a SYSTEM egység az utolsó kódszegmens, dszegmens amely minden programhoz automatikusan hozzászerkesztődik
Adatszegmens: Az adatszegmens egy közös, állandó adatterület. A főprogram és az összes egység ezt az adatterületet használja statikus adatainak tárolására. Az adatszegmens adat tartalmazza tehát a globális változókat és az összes típusos állandót. Az adatszegmens mérete is maximum 64 kbyte lehet. Ebből következik, hogy összességében ennél nagyobb terület nem áll rendelkezésünkre globális adataink számára. 64 kbyte-nál nagyobb területet elfoglaló adatszerkezetet nem adhatunk meg programunkban, és a szabványos egységekben deklarált adatok szintén az DSeg:$0000 adatszegmensből foglalják a helyet. helyet
Globális változók Típusos állandók
Az adatszegmens méretét a deklarált adatok határozzák meg, meg így az már a fordítás során eldől. Az adatszegmens szegmenscímét a processzor DS(Data Segment) regisztere tartalmazza, mely a program futása során DS állandó, értéke a System egység Dseg függvényével lekérdezhető. ny
Veremszegmens:
LIFO
A veremszegmenst a rendszer az adatok ideiglenes tárolására használja: ide kerülnek az eljárások és függvények lokális változói, paraméterei és visszatérési címei. mei A verem szegmenscíme és mérete a futás során állandó. A szegmenscímet a processzor SS (Stack Segment) regisztere tartalmazza, értéke a System egység Sseg függvényével lekérdezhető. ny A verem méretét (min. 1 kbyte, kbyte max. 64 kbyte) kbyte fordítás előtt meg lehet Sseg:SPtr adni ($M fordítási direktíva). va) Ha ezt nem tesszük, akkor a keretrendszerben megadott alapértelmezés lép érvénybe, amelynek szokásos értéke 16 kbyte körül SSeg:$0000 van. A verem lefelé növekszik. vekszik
Verem Szabad verem
A verem-mutató mutatja a következő elhelyezendő adat címét. Ez a verem szegmenscímétől számított relatív cím, mely kezdetben maximális, és ahogy telik a verem, úgy csökken az értéke. A verem-mutató a System egység SPtr függvényével lekérdezhető. ny
Overlay (átfedési) puffer: Ez a terület csak akkor része programunknak, ha átfedési (overlay) technikát alkalmazunk, egyébként a verem után közvetlenül a heap következik. vetkezik Az overlay technikát nagy programok esetén szokás használni, és lényege a következő: nem tartjuk bent egyszerre a tárban a teljes OvrHeapEnd lefordított programot, programot hanem annak csak az éppen futó részeit. Így a futó OvrHeapOrg programrészek átfedik egymást. A betöltéseket az Overlay egység automatikusan elvégzi a hivatkozott programelemek alapján.
Overlay puffer
A puffer elejét a System egységben található OvrHeapOrg, OvrHeapOrg végét az OvrHeapEnd függvénnyel nny kérdezhetjük le.
Heap:
halom, rakás
A heap egy dinamikus adattároló. A program futása közben dinamikus változókat lehet itt létrehozni illetve megszüntetni. ntetni A teljes heap bármekkora lehet, de egy dinamikus változó mérete nem lehet több 64 kbyte-nál. kbyte A heap minimális illetve maximális HeapEnd méretét a $M fordítási direktívával HeapPtr adhatjuk meg, ha ezt nem tesszük, akkor a keretrendszerben megadott alapértelmezés lép életbe, mely szerint HeapOrg a heap lefoglalja a teljes szabad memóriát. A heap veremszerűen működik, felfelé növekszik. vekszik
Szabad memória
Heap Overlay puffer
A területfoglalásokat és felszabadításokat, a foglalt és a szabad területek felügyeletét a heap-manager végzi, mely a System egység része. A heap mutató alatti részben vannak a program által lefoglalt dinamikus változók, a felette lévő rész szabad. A heap alját a System egység HeapOrg változója, tetejét a HeapEnd, HeapEnd a heap-mutatót a HeapPtr mutatja.
A Verem és a Heap méretének beállítása: {$M Veremméret , HeapMin , Heapmax} Veremméret: a verem pontos méretét állítjuk be (1024..65520) 1024..65520 HeapMin: az a minimális heapméret, amelyre a programnak mindenképpen szüksége van a futáshoz (0..655360) 0..655360 HeapMax: az a méret, amelynél több heap-et nem szeretnénk, ha a program lefoglalna még akkor sem, ha van annyi hely (HeapMin..655360) HeapMin..655360 A $M direktívát a főprogram elején kell megadni, elhagyása esetén a keretrendszerben megadott értékek a mérvadóak. retrendszer Ha a HeapMin-ben megadott terület a program futásakor nem áll rendelHeapMin kezésre, sre akkor a program nem indul el. el
A „Seg” és „Ofs” függvények: A függvények paramétere bármi lehet, aminek a memóriában címe van (változó, rutin, stb.).
A visszaadott érték WORD típusú - a kérdéses objektum szegmens illetve ofszet címe.
Például:
Seg(a) illetve Ofs(a)
Abszolút változó, rádefiniálás: Elképzehető olyan eset, amikor a programozó maga akarja meghatározni egy változó fizikai címét. Például amikor a ROM BIOS adatterület egy adatát szeretné programjából megváltoztatni (érdemes kerülni!) lni! vagy gyakoribb esetben a képernyőmemóriát akarja direkt módon elérni. rni Ekkor a deklaráció végén meg kell adnia a változó címét:
var valtozo_nev: típus ABSOLUTE Szegmens:Ofszet; Abszolút változó megadásakor nem történik memóriafoglalás, a változóhoz tartozó terület kezelésének felelőse a programozó. Abszolút változót csak indokolt esetben célszerű használni (sokszor csak kényelmi szempontból), mert a memória néhány részének megváltoztatása esetén a rendszer összeomolhat!!!
Például: A színes képernyő memória első karakterének abszolút deklarációja:
var elso_karakter : array[1..2] of byte : absolute $B800:0; vagy Mono monitor esetén az egész képernyő lefedésére alkalmas deklaráció:
type monitor_tipus = array[1..25,1..80,1..2] of byte; var monitor : monitor_tipus absolute $B000:0; stb.
...érdekesség: Egy abszolút változó deklarálásakor a konkrét fizikai cím helyett írhatunk egy másik változónevet is. Például:
var v1 : tipus1; v2 : tipus2 absolute v1; Így v2 címe megegyezik v1 címével. A rendszer v1 számára helyet foglal automatikusan, de v2 számára nem. v2 felügyelete teljes egészében a programozó dolga.
BALTA!!!
Jelen esetben v2-t v2 rádefiniáltuk v1-re. v1 BALTA!!! Ha tipus2 több memóriát foglal, mint tipus1, tipus1 akkor v2 „belelóg” a v1 utáni változóba.
Memóriatömbök: A memória direkt elérésére a Pascal-ban az egész memóriát lefedő tömböket definiálhatunk:
MEM [ Szegmens:Ofszet ] MEMW [ Szegmens:Ofszet ] MEML [ Szegmens:Ofszet ] A MEM tömb segítségével a memória egy adott címén található byte-ot írhatjuk illetve olvashatjuk. olvashatjuk MEMW esetén a hivatkozás WORD típusú. MEML esetén a hivatkozás LONGINT típusú. Például: MEM[$B800:I]:=Ord(‘*’);
…vége