學了半年的微機原理,對CPU的設計理論即思路有了一定的了解,深刻的體會到了這些最初設計者的高明之處
先說說CPU的工作模式
一般來說,80x86(80386及其後的各代CPU)可在實模式,保護模式和V86模式三種模式下運轉。實模式就是古老的MS-DOS的運作環境。Windows 9x隻利用了保護模式和V86模式。在保護模式下程式可以利用更多的記憶體(4GB),而運作在實模式下的16位程式最多隻能取1MB的記憶體(看出差别了吧,O(∩_∩)O)。如果你有一台128MB記憶體的機器運作在實模式下,那麼隻能利用1MB記憶體,其餘的全部浪費了。在這種情況下,你的386/486/586/PII/PIII隻能相當于一個跑的快的8086。v86則類似于實模式,可以調用BIOS, 但他能否調DOS功能,要看作業系統有沒有模拟DOS. 比如說,NT裡面16位程式可以正常使用DOS功能,因為NT提供了DOS模拟。 可Linux裡面 16位程式 隻能用 BIOS,沒有DOS給他用。
理論上,在保護模式下,一個程式可以尋址4096(4GB)的記憶體。這就是說,隻需要把程式編譯成32為的可執行程式(當然要借助32為編譯器),你就可以在程式中充分利用記憶體了。
從硬體結構上說,386由三個寄存器 CR0,CR1,CR2控制着CPU的運轉。比如說,CR0的第0位就是用來判斷目前CPU的工作模式還是實模式。我們知道8086/8088中有8個通用寄存器 AX 、BX、CX、DX、SI、DI、SP、BP這些寄存器都是16位的;在80386中這些寄存器都被擴充到了32為,即EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP,段寄存器增加了兩個FS和GS; 如果CPU運轉在實模式下,隻能利用這些32為寄存器的前(低)16位,而後(高)16位就浪費了。
段的概念是了解保護模式的關鍵所在。在實模式下,段寄存器中存放16位的段位址,這時段位址是參與尋址的;把段位址左移4位,加上偏移位址,就是20為的實體位址(嘿嘿,我們計算時就是把段位址加上個0,如CS:IP=1030:0010 則計算方法就是1030H--->10300H,加上偏移位址0010H,結果就是10310H就是20位實體位址)。 然而在保護模式下,段寄存器中存放着16位的段選擇器(Segment Selector),這個值不是直接的參與尋址的,而隻是一個指向段描述表(Segment Descriptor Table)的索引。段描述表中存放着段描述符(Segment Descriptor)。段描述符中有關于段的描述,比如段在記憶體中的位置,段的大小,段的類型(是資料段還是代碼段)等。
在此順便說一下虛拟記憶體吧
虛拟記憶體(Virtual Memory)顧名思義不是真正的記憶體,它隻是通過映射(Map)的方法,使用的虛拟位址(Virtual Address),能達到4GB(2的32次方,呵呵,結合上面介紹的知道為什麼在386中會有更大的‘記憶體’空間了吧)。而每個程式都可以被配置設定2GB的虛拟位址,剩下的2GB也就留給了作業系統使用(而這些空間是不允許使用者程式去通路,使用的進而保證了系統的安全性)。在Windows NT中,應用程式可有3GB的Virtual Address。
簡單的說說虛拟記憶體的實作方法和過程:
(1)、當一個應用程式被啟動時,作業系統就建立一個新程序,并給每個程序配置設定2GB的Virtual Address(not Memory);
(2)、虛拟記憶體管理器(Virtual Memory Manager)應将程式的代碼(code)映射(map) 到那個應用程式的虛拟位址中的某個位置,把目前所需要的代碼讀到實體位址中(注意:虛拟位址和應用程式代碼在實體記憶體中的位置是沒有關系的);
(3)、如果使用動态連結庫(Dynamic-Link Library,即DLL),DLL也被映射到程序的虛拟位址空間,在需要時才被讀入實體記憶體。(而根據動态連結庫的調用方式,即靜态調用,動态調用的方式不同,他們被映射的方式也不盡相同。靜态調用時每一個動态調用都會被當做程式的部分代碼而映射在代碼區,占用空間較大;而動态調用隻是被映射一次,隻是在需要時才進行調用);
(4)、其他項目(如資料,堆棧等)的空間是從實體記憶體中配置設定的,并被映射到虛拟位址空間中;
(5)、應用程式通過使用它的虛拟位址空間中的位址開始執行,然後虛拟記憶體管理器把每次的記憶體通路映射到實體位置;
呵呵,對于虛拟記憶體應該有個大體了解了吧,O(∩_∩)O 總之有這麼兩點:
一是應用程式是不會直接通路實體位址的;
二是虛拟記憶體管理器通過虛拟位址的通路請求,控制所有的實體位址通路。
虛拟記憶體的使用,簡化了記憶體的管理,并可彌補實體記憶體的不足;可以防止多任務(Multitasking)環境下各個應用程式之間的沖突。