引用:
作者ProtoZohar
不知道能不能請教RogerShih兄可能是很基本的問題  :那就是吃掉定址與記憶體的差異在哪啊?
另外是否可以稍微請RogerShih兄分析一下硬體映射區的前後差異、彼此間有怎樣的影響等等
以及是否可以針對「為了簡化系統中運作所有執行的程式有一個一致而簡單的設計」這點稍微講解一下?
希望可以多學一點,懇請RogerShih兄能解惑一下 
|
1. 如果你經歷過 DOS 時代,應該知道有些顯卡有段區域,一般是 A000:000 或 B000:0000 這兩段區域,當時很多顯卡記憶體可以超過 64K ,但你要存取顯示卡上的記憶體,如果用 IO 指令一般來說太慢,也太麻煩,所以通常是將資料寫入這之中一塊區域,將資料寫入顯卡裡。
這樣不但方便程式直接以 segment

ffset 定址去存取介面卡硬體資料,透過 DMA 等硬體機制,效能也更好。
不過因為當年是真實模式,程式的定址其實就等於真實定址,你要將定址跟真正存放資料的地方分開是不太可能的,不過也還是有一些軟體可以作到,如 QEMM 就可以把 640K 外能用的空間放出來用。
保護模式下,定址不像 8088、286 真實模式那樣直接,而改以 GDT 、LDT等表格法來定址,32位元 CPU 下這些表格多達8000~16000多個,每個表格都可以定址 4GB。但這裡的定址其實是虛擬定址,還得透過一個換算機制轉成真正的實際位址。
這中間,有很多技巧,可以讓硬體佔用的實際定址讓使用者看不到,或者映射到其他地方,甚至於讓資料暫存到硬碟去,其實,虛擬記憶體管理做的,簡單說來也就這麼回事。
2. 簡化是從程式設計面來看的,當我要呼叫一個系統函式,如果我跨節區 (如 selector 內容都不同),必須跨節區呼叫,系統浪費在呼叫上的資源,包括傳遞的參數,都會佔用很多資源。
尤其是多工環境下,透過技巧可以讓所有程式共享同一份系統呼叫程式,但彼此享用的資料資源又可以不互相干擾。
這部份很複雜,嚴格說來,微軟這種設計方式我記得是稱為 Flat 定址,所有 selector 都是相同的,這樣就不必跨節區呼叫,程式好寫很多,問題也比較少。
即使是 linux ,也要看 compiler 版本來決定,不過一般寫高階程式的不太需要關心這些細節就是了,只需要了解並在必要的時候選擇編譯器、連結器版本,來決定編譯出來的系統要以什麼樣的方式運作。
windows 的話,也就只能選擇 Server 產品了。